package cc.linker.steplink.crm.merchanth5.service.impl;

import cc.linker.steplink.crm.commons.FeeConstants;
import cc.linker.steplink.crm.commons.TradeTypeConstants;
import cc.linker.steplink.crm.commons.constant.DongConstant;
import cc.linker.steplink.crm.commons.constant.WcPayConstant;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.commons.model.WcPayProperties;
import cc.linker.steplink.crm.commons.utils.NumberUtils;
import cc.linker.steplink.crm.merchanth5.dao.MallBoomDao;
import cc.linker.steplink.crm.merchanth5.dao.MallDao;
import cc.linker.steplink.crm.merchanth5.dao.WxShareDao;
import cc.linker.steplink.crm.merchanth5.dao.acs.PurchaseProcessDao;
import cc.linker.steplink.crm.merchanth5.pojo.MerchantOrderGoodsPo;
import cc.linker.steplink.crm.merchanth5.pojo.acs.*;
import cc.linker.steplink.crm.merchanth5.service.*;
import cc.linker.steplink.crm.merchanth5.service.acs.PromoterClueService;
import cc.linker.steplink.crm.merchanth5.service.acs.PurchaseProcessNewService;
import cc.linker.steplink.crm.merchanth5.service.common.SmsService;
import cc.linker.steplink.crm.merchanth5.service.redis.GoodsService;
import cc.linker.steplink.crm.merchanth5.service.redis.ScoreActiveCacheService;
import cc.linker.steplink.crm.merchanth5.service.redis.SystemConfigService;
import cc.linker.steplink.crm.merchanth5.util.MapSortUtil;
import cc.linker.steplink.crm.merchanth5.util.ParamSignUtils;
import cc.linker.steplink.crm.merchanth5.util.Timer.TimerContext;
import cc.linker.steplink.crm.merchanth5.util.Timer.TimerScheduler;
import cc.linker.steplink.crm.response.GlobalException;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@EnableAsync
@Service
public class PurchaseProcessNewServiceImpl implements PurchaseProcessNewService {

    // 分账信息
    public static final String ACS_CREATE_ORDER_INFO = "ACS:CREATE_ORDER_INFO";

    // 单商品明细（退款和下发用）
    public static final String ACS_CREATE_GOODS_INFO = "ACS:CREATE_GOODS_INFO";

    // 全额金币抵扣（取消订单，或者自动取消订单用）
    public static final String CANCEL_SCORE_ORDER = "CANCEL:SCORE_ORDER_";

    // 调用返回结果
    public static final String ACS_CREATE_ORDER_RESULT = "ACS:CREATE_ORDER_RESULT";

    // 上下级关系
    public static final String ACS_CREATE_ORDER_SUBORDINATE = "ACS:CREATE_ORDER_SUBORDINATE";

    // 商品分享链路id
    public static final String ACS_CREATE_ORDER_LINK_ID = "ACS:CREATE_ORDER_LINK_ID";

    private static final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Value("${system.scrm.acsScrmWebUrl}")
    private String scrmH5Url;
    @Value("${casclient.clientHost}")
    private String clientHost;
    @Autowired
    private MallDao mallDao;
    @Autowired
    private PurchaseProcessDao purchaseProcessDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private MaiBaoLaService maiBaoLaService;
    @Autowired
    private ColumnService columnService;
    @Autowired
    private MallService mallService;
    @Autowired
    private OverViewInfoService overViewInfoService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private MallBoomService mallBoomService;
    @Autowired
    private MallBoomDao mallBoomDao;
    @Autowired
    private WxShareDao wxShareDao;
    @Autowired
    private SystemProperties systemProperties;
    @Autowired
    private HttpService httpService;
    @Autowired
    private WcPayProperties wcPayProperties;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private VipCustomerLogService vipCustomerLogService;
    @Autowired
    private ScoreActiveCacheService scoreActiveCacheService;
    @Autowired
    private PromoterClueService promoterClueService;

    /**
     * 获取签名
     * <p>
     * feeList（原来的totalFee包括分享人distributor，订单idorderId,是否分享 type,）
     */
    @Override
    public Map getSign2(Map<String, Object> param, String paySn, Integer payMode, List feeList, boolean rePay,
                        String orgId, Integer score, String customerId, List<Long> orderIds, String distributor) {
        Map<String, Object> qwe = new HashMap<>();
        qwe.put("aa", 123);
//        Object aa = 1/0;
        return qwe;
    }

    @Override
    public Map getSign(Map<String, Object> param, String paySn, Integer payMode, List feeList, boolean rePay,
                       String orgId, Integer score, String customerId, List<Long> orderIds, String distributor) {
        LOGGER.info("获取签名feelist--------》 " + JSON.toJSONString(feeList));
        LOGGER.info("获取签名distributor--------》 " + distributor);
        String res;
        // 签名数据，先去redis看看有没有
        String s = stringRedisTemplate.opsForValue().get(ACS_CREATE_ORDER_RESULT + paySn);
        String openid = (String) param.get("openid");
        // 如果是app来源 支付标识小程序
        String payType = "WX";
        if ("2".equals(param.get("orderSource").toString())) {
            param.put("acctType", "XCX");
            payType = "XCX";
        }
        if (!StringUtils.isEmpty(s)) {
            LOGGER.info("已经有签名=====");
            // 已生成签名
            res = s;
        } else {
            LOGGER.info("请求网关调用签名=====");
            // 购买商品，产生推荐费、服务费和平台费(包括小b商品)
            if (payMode == 1) {
                // wx
                res = this.buyGoodsFromSales(feeList, orgId, paySn, score, customerId, openid, payMode, payType, distributor, null);
            } else if (payMode == 2 || payMode == 3) {
                // tl
                param.put("openId", openid);
                param.put("customerId", customerId);
                param.put("orgId", orgId);
                maiBaoLaService.checkCustomerAccount(param, payMode);
                String frontUrl = "";
                if (!StringUtils.isEmpty(param.get("frontUrl"))) {
                    frontUrl = param.get("frontUrl").toString();
                }
                res = this.buyGoodsFromSales(feeList, orgId, paySn, score, customerId, openid, payMode, payType, distributor, frontUrl);
            } else {
                throw GlobalException.build("机构支付模式配置不正确");
            }
        }

        if (rePay) {
            // 知识付费支付未支付订单需要判断是否已经购买完成
            List<Map<String, Object>> orderInfoList = purchaseProcessDao.getOrderInfoByPaySn(paySn);
            if (orderInfoList != null && orderInfoList.size() == 1) {
                Map<String, Object> orderInfo = orderInfoList.get(0);
                Integer orderGoodsType = (Integer) orderInfo.get("orderGoodsType");
                if (orderGoodsType != null && orderGoodsType == 2) {
                    // 是知识付费
                    String orderGoodsId = (String) orderInfo.get("goodsId");
                    String columnGoodsId = purchaseProcessDao.getColumnGoodsIdByContentGoodsId(orderGoodsId);
                    if (columnGoodsId == null) {
                        columnGoodsId = "";
                    }
                    Map<String, Object> map = new HashMap<>();
                    map.put("goodsId", orderGoodsId);
                    map.put("customerId", customerId);
                    map.put("columnGoodsId", columnGoodsId);
                    boolean isPurchase = columnService.ifPurchase(map);
                    if (isPurchase) {
                        throw GlobalException.build("您已购买");
                    }
                }
            }
        }

        if (StringUtils.isEmpty(res)) {
            // 积分和优惠券抵扣后零元购买
            try {
                LOGGER.info("全积分抵扣：" + paySn);
                //this.zeroBuy(paySn);
                //全额抵扣
                Map params = new HashMap();
                params.put("orderSn", paySn);
                params.put("status", "20");
                params.put("txsn", "");
                params.put("type", 5);
                params.put("IsZeroBuy", "1");
                String paysKey = "paystatus:payorder_" + paySn;
                stringRedisTemplate.opsForValue().set(paysKey, "1");
                stringRedisTemplate.expire(paysKey, 1200, TimeUnit.SECONDS);
                stringRedisTemplate.opsForList().rightPush("callbackOrder:goodsPayCallBack", JSON.toJSONString(params));
            } catch (Exception e) {
                e.printStackTrace();
            }

            Map<String, Object> map = new HashMap<>();
            map.put("status", -3);
            map.put("orderSn", paySn);
            return map;
        }
        Map result = (Map) JSON.parse(res);
        result.put("orderSn", paySn);
//        LOGGER.info("请求签名3");
        return result;
    }

    /**
     * 定时关闭订单
     */
    protected void closeOrderAtRegularIntervals(List<Long> orderIds, Long scoreUse, String customerId, boolean isKnowledge) {
        TimerContext context = new TimerContext(3600, 1);
        TimerScheduler scheduler = new TimerScheduler(context);
        final List<Long> orderInfos = orderIds;
        scheduler.addTask(() -> {
            try {
                for (Long orderId : orderInfos) {
                    int result = mallDao.closeMerchantOrderInfo(orderId);
                    if (result > 0) {
                        List<MerchantOrderGoodsPo> goodsPoList = purchaseProcessDao.getOrderGoodsListByOrderId(orderId);
                        if (!isKnowledge) {
                            // 知识付费不用改库存
                            for (MerchantOrderGoodsPo goods : goodsPoList) {
                                Map<String, Object> params = new HashMap<>();
                                //恢复库存
                                params.put("goodsId", goods.getGoodsId());
                                params.put("skuKey", goods.getSkuKey());
                                params.put("goodsNum", goods.getBuyCount());
                                if (goods.getSkuKey() == null) {//未设置SKU
                                    int ifSku = mallDao.getIfGoodsSetSku(params);
                                    if (ifSku == 0) {
                                        mallDao.addGoodsCount(params);
                                    }
                                } else {//设置
                                    int rt = mallDao.addGoodsSkuCount(params);
                                    if (rt > 0) {
                                        mallDao.addGoodsCount(params);
                                    }
                                }
                            }
                        }
                        // 恢复积分
                        if (scoreUse > 0) {
                            purchaseProcessDao.addScoreByCustomerId(scoreUse, customerId);
                        }
                        // 恢复赠品
                        purchaseProcessDao.recoveryExerciseByOrderId(orderId);
                        // 删除赠品记录
                        purchaseProcessDao.deleteExerciseRecordByOrderId(orderId);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 3600);
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(scheduler, 0, context.getTickDuration() * 1000L);
    }

    private void zeroBuy(String orderSn) throws UnsupportedEncodingException {
        Map<String, Object> map = new HashMap<>();
        map.put("orderSn", orderSn);
        map.put("txsn", "");
        this.shopCallback(map);
    }


    /**
     * 购买商品回调
     *
     * @param param
     * @throws GlobalException
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public void shopCallback(Map<String, Object> param) throws GlobalException {
        LOGGER.info("订单回调参数----->" + JSON.toJSONString(param));
        String paySn = (String) param.get("orderSn");
        if (StringUtils.isEmpty(paySn)) {
            throw GlobalException.build("缺少参数");
        }
        Integer count = purchaseProcessDao.countTradeByPaySn(paySn);
        if (count > 0) {
            LOGGER.warn("该订单已支付完成" + param);
//            throw GlobalException.build("该订单已支付完成");
            return;
        }

        //获取订单列表
        String customerId = "";
        String orgId = "";
        String wxtransactionId = (String) param.get("txsn");
        //是否是虚拟商品
        Integer isVirtual = 0;
        List<Map<String, Object>> orderList = purchaseProcessDao.getOrderListByPaySn(paySn);
        if (orderList != null && orderList.size() > 0) {
            if (!StringUtils.isEmpty(orderList.get(0).get("customerId"))) {
                customerId = (String) orderList.get(0).get("customerId");
            }
            if (!StringUtils.isEmpty(orderList.get(0).get("orgId"))) {
                orgId = (String) orderList.get(0).get("orgId");
            }
            if (!StringUtils.isEmpty(orderList.get(0).get("isVirtual"))) {
                isVirtual = Integer.valueOf(orderList.get(0).get("isVirtual").toString());
            }

            // 建立上下级关系
            String subordinate = stringRedisTemplate.opsForValue().get(ACS_CREATE_ORDER_SUBORDINATE + paySn);
            if (!StringUtils.isEmpty(subordinate)) {
                String[] subordinates = subordinate.split("_");
                String pcustomerId = subordinates[1];
                if (!StringUtils.isEmpty(pcustomerId)) {
                    Map<String, Object> pCustomer = mallBoomDao.getCustomerInfoByCustomerId(pcustomerId);
                    if (orgId.equals(pCustomer.get("orgId"))) {
                        Map<String, Object> ret = new HashMap<>();
                        ret.put("pcustomerId", pcustomerId);
                        ret.put("customerId", subordinates[0]);
                        ret.put("parentShareWay", "shopping");
                        mallBoomService.saveCustomerParent(ret);
                    }
                }
            }

            Integer payMode = mallService.getPayModeByOrgId(orgId);
            String pid = purchaseProcessDao.getPidByCid(customerId);
            Map<String, Long> userRoleMap = purchaseProcessDao.getUserRoleMapByCustomerId(pid);
            Long c = userRoleMap.get("c");
            for (Map<String, Object> orderInfo : orderList) {
                String salerId = "";
                String orderSn = (String) orderInfo.get("orderSn");
                if (!StringUtils.isEmpty(orderInfo.get("salerId"))) {
                    salerId = (String) orderInfo.get("salerId");
                }
                String goodsName = (String) orderInfo.get("goodsName");
                String goodsId = (String) orderInfo.get("goodsId");
                //更新用户最后活跃时间
                wxShareDao.setCustomerLastInteraction(customerId);
                List<Map<String, Object>> goodsIdAndBuyNum = purchaseProcessDao.getGoodsIdAndBuyNumByOrderSn(orderSn);
                // 判断是否为知识付费商品
                boolean isKnowledge = false;
                if (goodsIdAndBuyNum.size() == 1) {
                    if (!StringUtils.isEmpty(goodsIdAndBuyNum.get(0).get("goodsType"))) {
                        Integer goodsType = Integer.valueOf(goodsIdAndBuyNum.get(0).get("goodsType").toString());
//                    Integer goodsType = purchaseProcessDao.getGoodsTypeByGoodsId(goodId);
                        if (goodsType == 3 || goodsType == 4) {
                            isKnowledge = true;
                        }
                    }
                }
                for (Map<String, Object> map : goodsIdAndBuyNum) {
                    //增加销量
                    addSaleNum(map);
                    // 更新赠品记录表状态
                    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                        @Override
                        public void afterCommit() {
                            String customerIds = (String) orderInfo.get("customerId");
                            // 更新赠品状态，发放体检券
                            updateExerciseRecord(map, customerIds);
                        }
                    });
                    //开通会员卡(异步)
                    String goodsIdp = "";
                    String goodsNamep = "";
                    if (!StringUtils.isEmpty(map.get("goodsId"))) {
                        goodsIdp = map.get("goodsId").toString();
                        if (!StringUtils.isEmpty(map.get("goodsName"))) {
                            goodsNamep = map.get("goodsName").toString();
                        }
                        vipCustomerLogService.openVipByGoodsId(goodsIdp, customerId, orgId, payMode, goodsNamep);
                    }
                    //异步
                    Integer promotion = 0;
                    if (!StringUtils.isEmpty(map.get("promotion"))) {
                        promotion = Integer.valueOf(map.get("promotion").toString());
                    }
                    String distributor = stringRedisTemplate.opsForValue().get("distributor:" + paySn);
                    if (!StringUtils.isEmpty(distributor)) {
                        String[] distributors = distributor.split("_");
                        String promoterId = distributors[1];
                        String customerIdp = distributors[0];
                        Map clueMap = new HashMap();
                        clueMap.put("promoterId", promoterId);
                        clueMap.put("customerId", customerIdp);
                        clueMap.put("actionType", isKnowledge ? 10 : 9);
                        clueMap.put("relevantId", goodsIdp);
                        clueMap.put("relevantName", goodsNamep);
                        Long amount = 0L;
                        if (!StringUtils.isEmpty(map.get("amount"))) {
                            amount = Long.valueOf(map.get("amount").toString());
                        }
                        clueMap.put("amount", NumberUtils.fenToYuan(amount));
                        clueMap.put("orderSn", orderSn);
                        clueMap.put("type", 2);
                        clueMap.put("orgId", orgId);
                        //增加销售线索
                        promoterClueService.addClue(clueMap);
                    }

                }


                // 购买支付完成后，给内容库发消息
                String linkId = stringRedisTemplate.opsForValue().get(ACS_CREATE_ORDER_LINK_ID + orderSn);

                if (!StringUtils.isEmpty(linkId)) {
                    Map<String, Object> map = new HashMap<>();
                    List<Map> goodsInfo = new ArrayList<Map>();
                    goodsIdAndBuyNum.forEach(a -> {
                        Map goods = new HashMap();
                        goods.put("goodsId", a.get("goodsId"));
                        goods.put("goodsName", a.get("goodsName"));
                        Long amount = 0L;
                        if (a.get("amount") != null) {
                            amount = Long.valueOf(a.get("amount").toString());
                        }
                        double v = amount.doubleValue() / 100;
                        String s = new BigDecimal(v).setScale(2, BigDecimal.ROUND_HALF_EVEN).toString();
                        goods.put("price", s);
                        goods.put("buyCount", a.get("buyCount"));
                        goodsInfo.add(goods);
                    });
                    map.put("goodsInfo", goodsInfo);
                    map.put("userId", customerId);
                    String customerName = purchaseProcessDao.getCustomerNameByCustomerId(customerId);
                    map.put("userName", customerName);
                    String time = LocalDateTime.now().format(df);
                    map.put("buyTime", time);
                    String openId = purchaseProcessDao.getOpenIdByCustomerId(customerId);
                    map.put("openId", openId);
                    String token = purchaseProcessDao.getTokenByOrgId(orgId);
                    map.put("token", token);
                    //String linkId = stringRedisTemplate.opsForValue().get(ACS_CREATE_ORDER_LINK_ID + orderSn);
                    map.put("linkId", linkId);
                    map.put("orderSn", orderSn);
                    LOGGER.info("给内容库发消息" + JSON.toJSONString(map));
                }

                //支付完成发送模板消息(调试要注释)
                Map<String, String> orderParam = new HashMap<>();
                orderParam.put("sendType", "payment");
                orderParam.put("orgId", orgId);
                orderParam.put("goodsName", goodsName);
                orderParam.put("orderSn", orderSn);
                orderParam.put("orderAmount", NumberUtils.fenToYuan(Long.valueOf(orderInfo.get("goodsAmount").toString())));
                String orderTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                orderParam.put("orderTime", orderTime);
                String h5url = scrmH5Url + "/userCenter.html?goto=orderlist?activeTab=20";
                String h5urlEncode = null;
                try {
                    h5urlEncode = URLEncoder.encode(h5url, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                String url = clientHost + "/personal/login?token=" + purchaseProcessDao.getTokenByOrgId(orgId) + "&m=" + h5urlEncode;
                orderParam.put("url", url);
                orderParam.put("openid", purchaseProcessDao.getOpenIdByCustomerId(customerId));
                //orgId-机构id,goodsName-商品名称,orderSn-订单号,orderAmount-订单金额(非支付金额),orderTime-支付时间,url-订单列表页面,openid-购买人的openid
                setTemplateMessageList(orderParam);

                List<Long> goodsIds = new ArrayList<>();
                // 保存商品动态
                for (Map<String, Object> map : goodsIdAndBuyNum) {
                    overViewInfoService.goodsData(map.get("goodsId").toString(), null, 3, null, null, null,
                            Integer.valueOf(map.get("buyCount").toString()), Integer.valueOf(map.get("amount").toString()), customerId, orgId, null);
                    Long goodsIa = Long.valueOf(map.get("goodsId").toString());
                    Integer goodsNum = Integer.valueOf(map.get("buyCount").toString());
                    if (goodsNum != null && goodsNum > 1) {
                        for (int i = 0; i < goodsNum; i++) {
                            goodsIds.add(goodsIa);
                        }
                    } else {
                        goodsIds.add(goodsIa);
                    }
                }
                String orderAmount = "";
                if (!StringUtils.isEmpty(orderInfo.get("orderAmount"))) {
                    orderAmount = orderInfo.get("orderAmount").toString();
                }
                try {
                    scoreActiveCacheService.setCache(orgId, orderSn, orderAmount, goodsIds, customerId);
                } catch (Exception e) {
                    LOGGER.info("计算赠送积分和成长值失败");
                }
                //region edit ckq  2020-06-10 修改update直接先查orderid 在update
                Integer orderId = purchaseProcessDao.getOrderIdByOrderSn(orderSn);
                if (StringUtils.isEmpty(orderId)) {
                    throw GlobalException.build("通过orderSn获取orderId失败");
                }
                //endregion
                Integer orderState = 20;
                Integer status = 1;
                if (isKnowledge) {
                    orderState = 40;
                    status = 2;
                }
                if (isVirtual == 1) {
                    orderState = 30;
                    status = 2;
                }
                // 更新订单状态
                purchaseProcessDao.updateOrderInfo(wxtransactionId, 1, orderState, orderSn);
                // 更新商品订单状态
                purchaseProcessDao.updateMerchantOrderGoodsInfo(status, orderId);

                if ("1".equals(param.get("IsZeroBuy"))) {
                    LOGGER.info("全额抵扣更新订单状态完成" + orderSn);
                }
                //不是知识付费的话需要进行购买推送
                if (!isKnowledge) {
                    // 商品购买推送
                    this.buyGoodsSmsPush(goodsIdAndBuyNum, orgId);
                    try {
                        // 调用江苏台erp同步接口
                        //externalOrderService.synchronizationOrder(orderSn);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                //异步执行文章操作
                this.updateBuyTimesByArticleId(orgId, goodsId, customerId);

                // 新增DealData记录
                Map<String, Object> dataMap = new HashMap<>();
                dataMap.put("objectId", orderSn);
                dataMap.put("orgId", orgId);
                dataMap.put("customerId", customerId);
                mallService.addToDealData(dataMap, 4);

                //
                Map<String, Long> salerRoleMap = purchaseProcessDao.getUserRoleMapByCustomerId(salerId);
                Long sc = salerRoleMap.get("c");
                if (c == 1 && sc == 1) {
                    // 上级是加盟代理的订单(用于统计数据)
                    // 或者分享人是加盟代理的订单
                    purchaseProcessDao.insertPromoterOrder(orderSn, 1);
                } else if (c == 1) {
                    purchaseProcessDao.insertPromoterOrder(orderSn, 2);
                } else if (sc == 1) {
                    purchaseProcessDao.insertPromoterOrder(orderSn, 3);
                }

            }

            if ("1".equals(param.get("IsZeroBuy"))) {
                LOGGER.info("全额抵扣记账开始" + paySn);
            }
            // 冻结时间
            Integer freezeTime = purchaseProcessDao.getFreezeTimeByOrgId(orgId);
            if (freezeTime == null || freezeTime < 0) {
                freezeTime = 30;
            }
            // 正常解冻时间
            String unFreezeTime = df.format(LocalDateTime.now()
                    .plusDays(freezeTime));

            // redis取分账信息
            String info = stringRedisTemplate.opsForValue().get(ACS_CREATE_ORDER_INFO + paySn);
            String goodsInfo = stringRedisTemplate.opsForValue().get(ACS_CREATE_GOODS_INFO + paySn);
            if (StringUtils.isEmpty(info) || StringUtils.isEmpty(goodsInfo)) {
                LOGGER.warn("订单已过期或无账单信息,orderSn===[{}]", paySn);
                return;
            }
            if ("1".equals(param.get("IsZeroBuy"))) {
                LOGGER.info("全额抵扣获取账单缓存成功" + paySn);
            }
            //插入单商品明细表
            this.insertGoodsProtectTradeInfo(goodsInfo, pid, orgId, payMode, unFreezeTime, customerId, wxtransactionId);

            List<TradeInfo> tradeInfoList = JSON.parseArray(info, TradeInfo.class);
            for (TradeInfo tradeInfo : tradeInfoList) {

                Integer tradeType = tradeInfo.getTradeType();
                if (tradeType != null && tradeType.equals(TradeTypeConstants.RECOMMENDS_FEE)) {
                    // 推荐费，需要更新接收用户id
                    if (!StringUtils.isEmpty(pid)) {
                        tradeInfo.setTo(pid);
                    }
                }
                Integer payType = tradeInfo.getPayType();
                switch (payType) {
                    case 1: {
                        // 现金
                        String to = tradeInfo.getTo();
                        Integer receiveRole = tradeInfo.getReceiveRole();
                        Integer balance;
                        switch (receiveRole) {
                            // 根据收款人角色，判断给哪个表加，在哪个表查余额。
                            // 先加，再取余额，再记录
                            case 0:
                                balance = 0;
                                break;
                            case 1:
                                // 大b
                                purchaseProcessDao.updateOrgAccountFreeze(tradeInfo);
                                balance = purchaseProcessDao.getOrgBalanceByOrgId(to);
                                break;
                            case 2:
                                // 小b
                                purchaseProcessDao.updateSalesAccountFreeze(tradeInfo);
                                balance = purchaseProcessDao.getSalesBalanceByCustomerId(to);
                                stringRedisTemplate.delete("home:customer_info_" + to);
                                break;
                            case 3:
                            case 4:
                            case 5:
                                // 普通用户
                                purchaseProcessDao.updateCustomerAccountFreeze(tradeInfo);
                                balance = purchaseProcessDao.getUserBalanceByCustomerId(to);
                                stringRedisTemplate.delete("home:customer_info_" + to);
                                break;
                            default:
                                balance = 0;
                                break;
                        }

                        Map<String, Object> map = new HashMap<>();
                        map.put("orgId", orgId);
                        map.put("payMode", payMode);
                        map.put("orderName", tradeInfo.getOrderName());
                        map.put("balance", balance);
                        map.put("orderSn", tradeInfo.getOrderSn());
                        map.put("tradeInfo", tradeInfo);
                        boolean isKnowledge = false;
                        if (tradeInfo != null && tradeInfo.getIsKnowledge() != null) {
                            isKnowledge = tradeInfo.getIsKnowledge();
                        }
                        map.put("unFreezeTime", isKnowledge ? unFreezeTime : null);
                        // 生成业务单号
                        String busiSn = this.generateBusiSn(tradeInfo.getTradeType(), customerId);
                        map.put("busiSn", busiSn);
                        map.put("serialNo", wxtransactionId);

                        purchaseProcessDao.insertProtectTradeInfo(map);
                        break;
                    }
                    case 2: {
                        // 积分
                        String to = tradeInfo.getTo();
                        Integer balance;
                        if (tradeInfo.getTradeType() != 0) {
                            // 0为支出，已在创建时扣除，只需记录
                            purchaseProcessDao.addScoreByCustomerId(tradeInfo.getAmount().longValue(), tradeInfo.getTo());
                            balance = purchaseProcessDao.getCustomerScoreBalanceByCustomerId(to);
                            //金币记录
                            Map<String, Object> scoreLog = new HashMap<>();
                            scoreLog.put("customerId", tradeInfo.getTo());
                            scoreLog.put("score", tradeInfo.getAmount());
                            scoreLog.put("type", 1);
                            scoreLog.put("orderSn", tradeInfo.getOrderSn());
                            scoreLog.put("recId", tradeInfo.getRecId());
                            purchaseProcessDao.addScoreLog(scoreLog);
                        } else {
                            Integer receiveRole = tradeInfo.getReceiveRole();
                            switch (receiveRole) {
                                case 1:
                                    // 大b
//                                    purchaseProcessDao.updateOrgAccountFreeze(tradeInfo);
                                    balance = purchaseProcessDao.getOrgBalanceByOrgId(to);
                                    break;
                                case 2:
                                    // 小b
//                                    purchaseProcessDao.updateSalesAccountFreeze(tradeInfo);
                                    balance = purchaseProcessDao.getSalesBalanceByCustomerId(to);
                                    break;
                                default:
                                    balance = 0;
                                    break;
                            }
                        }
                        Map<String, Object> map = new HashMap<>();
                        map.put("orgId", orgId);
                        map.put("payMode", payMode);
                        map.put("orderName", tradeInfo.getOrderName());
                        map.put("balance", balance);
                        map.put("orderSn", tradeInfo.getOrderSn());
                        map.put("tradeInfo", tradeInfo);
                        boolean isKnowledge = false;
                        if (tradeInfo != null && tradeInfo.getIsKnowledge() != null) {
                            isKnowledge = tradeInfo.getIsKnowledge();
                        }
                        map.put("unFreezeTime", isKnowledge ? unFreezeTime : null);
                        // 生成业务单号
                        String busiSn = this.generateBusiSn(tradeInfo.getTradeType(), customerId);
                        map.put("busiSn", busiSn);
                        map.put("serialNo", wxtransactionId);

                        purchaseProcessDao.insertProtectTradeInfo(map);
                        break;
                    }
                    default:
                        break;
                }
            }
        }
    }

    /**
     * 插入单商品明细表
     */
    @Override
    public void insertGoodsProtectTradeInfo(String goodsInfo, String pid, String orgId, Integer payMode, String unFreezeTime, String customerId, String wxtransactionId) {
        List<TradeInfo> tradeInfoList = JSON.parseArray(goodsInfo, TradeInfo.class);
        for (TradeInfo tradeInfo : tradeInfoList) {

            Integer tradeType = tradeInfo.getTradeType();
            if (tradeType != null && tradeType == 3) {
                // 推荐费，需要更新接收用户id
                if (!StringUtils.isEmpty(pid)) {
                    tradeInfo.setTo(pid);
                }
            }
            Integer payType = tradeInfo.getPayType();
            switch (payType) {
                case 1: {
                    // 现金
                    String to = tradeInfo.getTo();
                    Integer receiveRole = tradeInfo.getReceiveRole();
                    Integer balance;
                    switch (receiveRole) {
                        // 根据收款人角色，判断在哪个表查余额。
                        // 取余额，记录
                        case -1:
                            balance = 0;
                            break;
                        case 0:
                            balance = 0;
                            break;
                        case 1:
                            // 大b
                            balance = purchaseProcessDao.getOrgBalanceByOrgId(to);
                            break;
                        case 2:
                            // 小b
                            balance = purchaseProcessDao.getSalesBalanceByCustomerId(to);
                            break;
                        case 3:
                        case 4:
                        case 5:
                            // 普通用户
                            balance = purchaseProcessDao.getUserBalanceByCustomerId(to);
                            break;
                        default:
                            balance = 0;
                            break;
                    }
                    Map<String, Object> map = new HashMap<>();
                    map.put("orgId", orgId);
                    map.put("payMode", payMode);
                    map.put("orderName", tradeInfo.getOrderName());
                    map.put("balance", balance);
                    map.put("orderSn", tradeInfo.getOrderSn());
                    Long recId = null;
                    if (tradeInfo != null && tradeInfo.getRecId() != null) {
                        recId = tradeInfo.getRecId();
                    }
                    map.put("recId", recId);
                    map.put("tradeInfo", tradeInfo);
                    boolean isKnowledge = false;
                    if (tradeInfo != null && tradeInfo.getIsKnowledge() != null) {
                        isKnowledge = tradeInfo.getIsKnowledge();
                    }
                    map.put("unFreezeTime", isKnowledge ? unFreezeTime : null);
                    // 生成业务单号
                    String busiSn = this.generateBusiSn(tradeInfo.getTradeType(), customerId);
                    map.put("busiSn", busiSn);
                    map.put("serialNo", wxtransactionId);

                    purchaseProcessDao.insertGoodsProtectTradeInfo(map);
                    break;
                }
                case 2: {
                    // 积分
                    String to = tradeInfo.getTo();
                    Integer balance;
                    if (tradeInfo.getTradeType() != 0) {
                        // 0为支出，已在创建时扣除，只需记录
                        balance = purchaseProcessDao.getCustomerScoreBalanceByCustomerId(to);
                    } else {
                        Integer receiveRole = tradeInfo.getReceiveRole();
                        switch (receiveRole) {
                            case 1:
                                // 大b
                                balance = purchaseProcessDao.getOrgBalanceByOrgId(to);
                                break;
                            case 2:
                                // 小b
                                balance = purchaseProcessDao.getSalesBalanceByCustomerId(to);
                                break;
                            default:
                                balance = 0;
                                break;
                        }
                    }
                    Map<String, Object> map = new HashMap<>();
                    map.put("orgId", orgId);
                    map.put("payMode", payMode);
                    map.put("orderName", tradeInfo.getOrderName());
                    map.put("balance", balance);
                    map.put("orderSn", tradeInfo.getOrderSn());
                    Long recId = null;
                    if (tradeInfo != null && tradeInfo.getRecId() != null) {
                        recId = tradeInfo.getRecId();
                    }
                    map.put("recId", recId);
                    map.put("tradeInfo", tradeInfo);
                    boolean isKnowledge = tradeInfo.getIsKnowledge();
                    map.put("unFreezeTime", isKnowledge ? unFreezeTime : null);
                    // 生成业务单号
                    String busiSn = this.generateBusiSn(tradeInfo.getTradeType(), customerId);
                    map.put("busiSn", busiSn);
                    map.put("serialNo", wxtransactionId);
                    purchaseProcessDao.insertGoodsProtectTradeInfo(map);
//                    purchaseProcessDao.insertProtectTradeInfo(map);
                    break;
                }
                default:
                    break;
            }
        }
    }

    /**
     * 生成业务单号
     * 前缀+13位时间戳+用户id//异步执行文章操作
     */
    @Override
    public String generateBusiSn(Integer tradeType, String customerId) {
        String prefix = "";
        switch (tradeType) {
            // rmb交易类型：0-提现，1-商品成交收益，2-商品服务费，3-商品推荐费，4-商品平台费(大b)，5-开通联盟商家平台费，
            // 6-开通联盟商家收益，7-开通加盟代理平台费，8-开通加盟代理收益，9-商品平台费(联汇)，10-商城商品收益，11-提现手续费
            case 1:
            case 10:
                prefix = "AB";
                break;
            case 2:
                prefix = "AE";
                break;
            case 3:
                prefix = "AF";
                break;
            case 4:
                prefix = "AC";
                break;
            case 5:
                prefix = "BD";
                break;
            case 6:
                prefix = "BB";
                break;
            case 7:
                prefix = "CD";
                break;
            case 8:
            case 13:
                prefix = "CB";
                break;
            case 9:
                prefix = "AD";
                break;
            case 12:
                prefix = "F";
                break;
            case 20://开通联盟商家平台抽成（大麦）
                prefix = "BC";
                break;
            case 21://开通加盟代理平台抽成（大麦）
                prefix = "CC";
                break;
            case 31://31-体检费用
                prefix = "I";
                break;
            case 32://32-体检分佣
                prefix = "IB";
                break;
            case 33://33-体检充值
                prefix = "J";
            default:
                break;
        }
        return prefix + System.currentTimeMillis() + customerId;
    }

    //异步执行文章操作
    @Async
    protected void updateBuyTimesByArticleId(String orgId, String goodsId, String customerId) {
        // 机器人开启状态
        Integer robotStatus = mallDao.getRobotStatusByOrgId(orgId);
        if (robotStatus != null && robotStatus == 1) {
            String[] split = goodsId.split(",");
            for (String s : split) {
                // 获得商品关联文章id
                List<String> articleId = mallDao.getArticleIdByGoodsId(Long.valueOf(s));
                if (articleId != null && articleId.size() > 0) {
                    // 如果文章id不为空
                    Map<String, Object> map = new HashMap<>();
                    map.put("customerId", customerId);
                    map.put("newsId", articleId);
                    // 找到24小时内发送过的文章
                    String oneArticleId = mallDao.getArticleIdSendWithinOneDayByNewsId(map);
                    if (!StringUtils.isEmpty(oneArticleId)) {
                        mallDao.updateBuyTimesByArticleId(oneArticleId);
                    }
                }
            }
        }
    }

    @Async
    @Override
    public void buyGoodsSmsPush(List<Map<String, Object>> goodsIdAndBuyNum, String orgId) {
        // 商品购买推送 只有普通商品成交后进行推送，知识付费商品、报名等等其他付费项不进行推送
        List<String> belongIdList = goodsIdAndBuyNum.stream()
                .map(x -> (String) x.get("belongId"))
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        // 提醒手机号
        StringBuilder remindPhone = new StringBuilder();
        Map<String, Object> map = new HashMap<>();
        map.put("businessType", "9010");
        if (belongIdList.contains("")) {
            // 包含大b的商品，取大b的手机号
            String orgRemindPhone = purchaseProcessDao.getRemindPhoneByOrgId(orgId);
            if (!StringUtils.isEmpty(orgRemindPhone)) {
                remindPhone.append(orgRemindPhone).append(",");
            }
        }
        // 小b商品手机号
        String belongRemindPhone = purchaseProcessDao.getRemindPhoneByBelongIdList(belongIdList);
        if (!StringUtils.isEmpty(belongRemindPhone)) {
            remindPhone.append(belongRemindPhone);
        }
        if (remindPhone.length() == 0) {
            return;
        }
        map.put("mobilNumber", remindPhone.toString());
        map.put("params", "");
        String s = smsService.sendMsg(orgId, map);
        LOGGER.info("smsService.sendMsg.result===[{}]", s);
    }

    @Override
    public void setTemplateMessageList(Map data) {
    }

    /**
     * 购买商品(1.11新增大b也会产生分润)
     *
     * @param : feeList 订单商品列表
     * @param : orgId 机构id
     * @param : paySn 合单订单号
     * @param : allScore 总金币
     * @param : customerId 用户id
     * @param : openid 支付的openid
     * @param : payMode 支付模式 微信  通联  云听荟通联
     * @param : payType 支付类型 微信  小程序
     * @param : distributor 分享用户
     * @param : frontUrl 支付完成后跳转地址
     */
    private String buyGoodsFromSales(List<Map<String, Object>> feeList, String orgId, String paySn, Integer allScore, String customerId,
                                     String openid, Integer payMode, String payType, String distributor, String frontUrl) throws GlobalException {
        //订单明细
        List<Map<String, Object>> tradeInfos = new ArrayList<Map<String, Object>>();
        //单商品明细（退款和下发用）
        List<Map<String, Object>> goodsTradeInfos = new ArrayList<Map<String, Object>>();
        //总付款
        int totalPay = 0;
        //是否为知识付费（知识付费只能直接购买）
        boolean isKnowledge = false;
        //通联分钱参数列表
        List<TlResultPo> tlResultList = new ArrayList<>();
        if (feeList.size() == 1) {
            //如果是单订单并且单商品判断是否是知识商品
            List<MerchantOrderGoodsPo> goodsList = (List<MerchantOrderGoodsPo>) feeList.get(0).get("goodsList");
            if (goodsList.size() == 1) {
                MerchantOrderGoodsPo goods = goodsList.get(0);
                Integer goodsType = goods.getGoodsType();
                if (goodsType != null && (goodsType.equals(3) || goodsType.equals(4))) {
                    isKnowledge = true;
                }
            }
        }
        for (Map<String, Object> totalFee : feeList) {
            List<MerchantOrderGoodsPo> goodsList = (List<MerchantOrderGoodsPo>) totalFee.get("goodsList");
            String orderSn = totalFee.get("orderSn").toString();
            //供货商机构
            String mallsOrgId = orgId;
            //订单总支付
            int allPay = 0;
            //商品总收益
            int totalIncome = 0;
            int totalIncomeScore = 0;
            //订单中是否存在大b反润商品
            boolean ifRebateToOrg = false;
            //商品的归属人（belongId有则为小b）
            String belongId = "";
            //订单总名称
            String orderName = "";
            // 订单是否产出推荐费给推荐人
            Boolean ifRfOrder = false;
            // 订单是否产出服务费给分享人
            Boolean ifFwOrder = false;
            // 订单是否产出创作费给创作人
            Boolean ifCzOrder = false;
            // 订单未产生费用给谁 1-商家2-机构
            Integer unhappen = 1;
            // 订单返利值(推荐费)2
            Integer recomPriceOrder = 0;
            // 订单返利值(推荐费)3
            Integer originalPriceOrder = 0;
            // 1-sharePrice-分享人（联汇子账户） 2-recomPrice-推荐人（联汇子账户）3-platformFee-联汇（联汇子账户） 4-income-商品拥有者（小b账户）
            // 1+2+3 先打到联汇账户，多出来的打给小b账户，然后联汇打积分抵扣的金额给小b账户
            // 大b抽成
            Integer platformPriceOrder = 0;
            // 返利值(服务费)1
            Integer sharePriceOrder = 0;
            // 返利值(服务费)1金币
            Integer sharePriceNormal = 0;
            // 联汇抽成
            Integer linkerFeeOrder = 0;
            // 支付抽成
            Integer unionBarleyFeeOrder = 0;
            //商品收益
            Integer goodsTotalPriceOrder = 0;
            //交易手续费支出
            Integer processFeeOrder = 0;
            //返润佣金
            Integer profitFeeOrder = 0;
            //是不是销售商品
            boolean isSaleOrder = false;
            //供货商商品的belongId，为空则是大b
            String mallsBelongId = "";
            //推广佣金(通联)
            Integer spreadFeeOrder = 0;
            //推广佣金(记账)
            Integer spreadFeeTrade = 0;
            //商品收益金币抵扣
            Integer incomeScoreOrder = 0;
            //反润佣金抵扣的金币
            Integer spreadFeeScoreOrder = 0;
            //推荐费抵扣的金币
            Integer recomPriceScoreOrder = 0;
            //服务费抵扣的金币
            Integer sharePriceScoreOrder = 0;
            //普通用户服务费抵扣的金币
            Integer sharePriceNormalScoreOrder = 0;
            //联汇抽成抵扣的金币
            Integer linkerFeeScoreOrder = 0;
            //抽成抵扣的金币
            Integer unionBarleyFeeScoreOrder = 0;
            //创作费抵扣的金币
            Integer originalPriceScoreOrder = 0;
            //大b平台费抵扣的金币
            Integer platformPriceScoreOrder = 0;
            //是否亏损
            Integer isLoss = 0;
            //供货商亏损差额
            Integer mallsLossAmount = 0;
            //销售商亏损差额
            Integer salerLossAmount = 0;
            //订单的抵扣金币
            Integer scoreOreder = 0;
            //订单优惠金额
            Integer couponAmountOreder = 0;
            for (MerchantOrderGoodsPo goods : goodsList) {
                // 购买商品，计算推荐费和服务费
                Long id = goods.getGoodsId();
                Long skuId = goods.getSkuId();
                Long recId = goods.getRecId();
                Integer score = 0;
                Integer couponAmount = 0;
                if (goods.getPaymentPoints() != null && goods.getPaymentPoints() > 0) {
                    score = goods.getPaymentPoints();
                    scoreOreder += score;
                }
                if (goods.getCouponAmount() != null && Integer.valueOf(goods.getCouponAmount()) > 0) {
                    couponAmount = Integer.valueOf(goods.getCouponAmount());
                    couponAmountOreder += couponAmount;
                }

                //创作费（创作人）
                String author = goods.getAuthor();
                //服务费（分享人）
                String distributorFw = goods.getSalerId();
                //获取商品信息
                GoodsParamPo goodsParamPo = goodsService.getGoodsParamPoByGoodsId(id);
                //是否反润
//                Integer type =  purchaseProcessDao.getPromotionByGoodsId(id);
                Integer type = goodsParamPo.getType();
                //关联供货商品ID(判断是不是销售商品)
//                Long mallsGoodsId =  purchaseProcessDao.getMallsGoodsIdByGoodsId(id);
                Long mallsGoodsId = goodsParamPo.getMallsGoodsId();
                //是不是销售商品
                boolean isSale = false;
                if (!StringUtils.isEmpty(mallsGoodsId)) {
                    isSale = true;
                    isSaleOrder = true;
                }
                //供货商品供货价
                Integer mallsGoodsPrice = 0;
                //供货商品价格
                Integer mallsGoodsTotalPrice = 0;
                if (isSale) {
                    //获取商品信息
                    GoodsParamPo mallsGoodsParamPo = goodsService.getGoodsParamPoByGoodsId(mallsGoodsId);
                    mallsOrgId = mallsGoodsParamPo.getOrgId();
                    mallsBelongId = mallsGoodsParamPo.getBelongId();

                    Long mallSkuId = null;
                    if (skuId != null) {
                        //通过商品ID和SKUID去缓存中拿取mallsskuid
                        mallSkuId = goodsService.getCreateOrderMallsSkuId(id, skuId);
                    }
                    //获取供货商价格
                    mallsGoodsPrice = goodsService.getCreateOrderMallsAmount(id, skuId);
                    mallsGoodsTotalPrice = mallsGoodsPrice * goods.getBuyCount() + goods.getShippingFee();
                }
                // 返润模式
                Map<String, Integer> reverseProfitModel = systemConfigService.getOrgPaySetting(orgId);

                // 商品服务费占比例,eg:50
                Integer serviceRatio;
                // 商品推荐费比例
                Integer recommendRatio;
                // 商品创作费比例
                Integer originalRatio;
                if (reverseProfitModel == null) {
                    // 机构没有设置返润模式
                    serviceRatio = 50;
                    recommendRatio = 50;
                    originalRatio = 0;
                    unhappen = 1;
                } else {
                    serviceRatio = reverseProfitModel.get("serviceRatio");
                    recommendRatio = reverseProfitModel.get("recommendRatio");
                    originalRatio = reverseProfitModel.get("originalRatio");
                    unhappen = reverseProfitModel.get("unhappen");
                }
                // 总返利,eg:20
//                String rebateStr = purchaseProcessDao.getPromotionStrRebateByGoodsId(id);
                String rebateStr = goodsParamPo.getRebateStr();
                if (StringUtils.isEmpty(rebateStr)) {
                    rebateStr = "0";
                }
                Long goodsPrice = goods.getAmountCent() * goods.getBuyCount();
                Double rebate = Double.valueOf(rebateStr);
                // 服务费比例,eg:10
                double i = rebate * serviceRatio.doubleValue() / 100;
                // 推荐费比例,eg:10
                double j = rebate * recommendRatio.doubleValue() / 100;
                // 创作费比例,eg:10
                double k = rebate * originalRatio.doubleValue() / 100;
                // 服务费
                double iv = goodsPrice.doubleValue() * i / 100;
                // 推荐费
                double jv = goodsPrice.doubleValue() * j / 100;
                // 创作费
                double kv = goodsPrice.doubleValue() * k / 100;
                // 返利值(服务费)1
                int sharePrice = new BigDecimal(iv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
                // 返利值(推荐费)2
                int recomPrice = new BigDecimal(jv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
                // 返利值(创作费)3
                int originalPrice = new BigDecimal(kv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
                // 总返利值比例
                double goodsAllRebate = goodsPrice.doubleValue() * rebate / 100;
                // 总返利值
                int totalPrice = new BigDecimal(goodsAllRebate).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
                // 返利值(平台费)3
                int platformPrice = totalPrice - sharePrice - recomPrice - originalPrice;
                if (platformPrice < 0) {
                    // 推荐费服务费创作费都进位，平台费为0，导致总返利减去推荐费和服务费结果为-1，需要调整费用
                    platformPrice = 0;
                    if (totalPrice - recomPrice - originalPrice > 0) {
                        sharePrice = totalPrice - recomPrice - originalPrice;
                    } else if (totalPrice - recomPrice > 0) {
                        sharePrice = 0;
                        recomPrice = totalPrice - recomPrice;
                    }
                }
                // 商品价格+运费
                int goodsTotalPrice = (goodsPrice).intValue() + goods.getShippingFee() - Integer.valueOf(goods.getCouponAmount());
                // 用户实付金额
                int pay = goodsTotalPrice - score;
                allPay = allPay + pay;

                //机构反润信息
                Map<String, String> platformRateMap = systemConfigService.getPlatformRateMap(mallsOrgId);

                if (platformRateMap == null || platformRateMap.size() == 0) {
                    platformRateMap.put("linkerRate", "0");
                    platformRateMap.put("unionBarleyTake", "0");
                }
                // lh抽成
                Double linkerTake = Double.valueOf(platformRateMap.get("linkerRate"));
                // 大b抽成
                Double unionBarleyTake = Double.valueOf(platformRateMap.get("unionBarleyTake"));

                totalFee.put("score", score);
                // 联汇抽成
                double v2 = pay * linkerTake / 100;
                int linkerFee = new BigDecimal(v2).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
                // 大麦抽成
                double v3 = pay * unionBarleyTake / 100;
                int unionBarleyFee = new BigDecimal(v3).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
                if ((linkerTake + unionBarleyTake) == 10) {
                    double all = pay * 0.1;
                    int allfee = new BigDecimal(all).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
                    unionBarleyFee = allfee - linkerFee;
                }
                // 平台费3
                int platformFee = linkerFee + unionBarleyFee;
                // 1-sharePrice-分享人（联汇子账户） 2-recomPrice-推荐人（联汇子账户）3-platformFee-联汇（联汇子账户） 4-income-商品拥有者（小b账户）
                // 1+2+3 先打到联汇账户，多出来的打给小b账户，然后联汇打积分抵扣的金额给小b账户
                int lh = totalPrice + platformFee;
//                if (pay < lh) {
//                    throw GlobalException.build("用户支付金额不足");
//                }
                // 商品所属人id
//                belongId = purchaseProcessDao.getBelongIdByGoodsId(id);
                belongId = goodsParamPo.getBelongId();
                if (!isSale) {
                    mallsBelongId = belongId;
                }
                // 是否为大b需要反润的商品(1.11新增)
                if (StringUtils.isEmpty(belongId) && type == 1) {
                    ifRebateToOrg = true;
                }

                // 上级id
                String pid = purchaseProcessDao.getPidByCid(customerId);
                // 是否产出创作费给创作人
                boolean ifCz = !StringUtils.isEmpty(author);
                if (ifCz) {
                    ifCzOrder = ifCz;
                }
                // 是否产出推荐费给推荐人
                boolean ifRf = !StringUtils.isEmpty(pid) && recomPrice != 0 && !pid.equals(customerId);
                boolean recommend = false;
                if ((ifRebateToOrg && !StringUtils.isEmpty(distributor)) || (!StringUtils.isEmpty(belongId) && !StringUtils.isEmpty(distributor) && type == 1)) {
                    recommend = true;
                }
                // 若本没有推荐费，且有临时推荐人，那么先将临时推荐人作为推荐人
                if (!ifRf && recommend) {
                    ifRf = true;
                    pid = distributor;
                }

                if (!StringUtils.isEmpty(pid)) {
                    // 推广员不返推荐费
                    Map<String, Long> role = purchaseProcessDao.getUserRoleMapByCustomerId(pid);
                    //联盟商家
                    Long a = role.get("a");
                    //推广员
                    Long b = role.get("b");
                    //加盟代理
                    Long c = role.get("c");
                    if (a == 0 && b == 1 && c == 0) {
                        ifRf = false;
                    }
                    if (c == 0) {
                        ifRf = false;
                    }
                }
                // 是否产出服务费给分享人
                boolean ifFw = !StringUtils.isEmpty(distributorFw) && sharePrice != 0 && !distributorFw.equals(customerId);
                // 分享人是否是普通用户(是普通用户只分金币)
                boolean distributorIsNormal = false;
                if (ifFw) {
                    distributorIsNormal = this.getUserRole(distributorFw);
                }
                String linkId = "";
                orderName = orderName + "," + goods.getGoodsName();
                //推荐费服务费平台费的trade
                // 商品收益=订单总金额-总返利-平台费4
//                Integer income = pay - totalPrice - platformFee;
                Integer income = goodsTotalPrice - totalPrice - platformFee;
                TradeParamPo tradeParamPo = new TradeParamPo(score, sharePrice, recomPrice, income, unionBarleyFee, platformPrice, linkerFee, originalPrice);
                Map tradeInfolistMap = this.getTradeInfo(tradeParamPo, ifFw, distributor, distributorFw, customerId, ifRebateToOrg, mallsOrgId, belongId, ifRf,
                        pid, unhappen, linkId, orderSn, recId, distributorIsNormal, ifCz, author, orgId);
                List<Map<String, Object>> tradeInfolist = (List<Map<String, Object>>) tradeInfolistMap.get("tradeInfos");
                tradeParamPo = (TradeParamPo) tradeInfolistMap.get("tradeParamPo");
                if (ifRf) {
                    ifRfOrder = true;
                }
                if (ifFw) {
                    ifFwOrder = true;
                }
                if (ifFw) {
                    if (distributorIsNormal) {
                        sharePriceNormal = sharePriceNormal + sharePrice - tradeParamPo.getSharePriceScore();
                        sharePriceNormalScoreOrder += tradeParamPo.getSharePriceScore();
                    } else {
                        sharePriceOrder = sharePriceOrder + sharePrice - tradeParamPo.getSharePriceScore();
                        sharePriceScoreOrder += tradeParamPo.getSharePriceScore();
                    }
                }
                if (ifRf) {
                    recomPriceOrder = recomPriceOrder + recomPrice - tradeParamPo.getRecomPriceScore();
                }
                if (ifCz) {
                    originalPriceOrder = originalPriceOrder + originalPrice - tradeParamPo.getOriginalPriceScore();
                }
                Integer incomeScore = tradeParamPo.getIncomeScore();
                recomPriceScoreOrder += tradeParamPo.getRecomPriceScore();
                linkerFeeScoreOrder += tradeParamPo.getLinkerFeeScore();
                unionBarleyFeeScoreOrder += tradeParamPo.getUnionBarleyFeeScore();
                originalPriceScoreOrder += tradeParamPo.getOriginalPriceScore();
                platformPriceScoreOrder += tradeParamPo.getPlatformPriceScore();
                income = tradeParamPo.getIncome();
                //未产生的费用
                Integer unhappenFee = (Integer) tradeInfolistMap.get("unhappenFee");
                //返润佣金（总返润-未产生的费用）
                Integer profitFee = totalPrice;
                if (unhappen == 1) {
                    profitFee = profitFee - unhappenFee;
                }
                unionBarleyFee = tradeParamPo.getUnionBarleyFee();
                platformPrice = tradeParamPo.getPlatformPrice();
//                unionBarleyFeeOrder = unionBarleyFeeOrder + unionBarleyFee - tradeParamPo.getUnionBarleyFeeScore() - tradeParamPo.getPlatformPriceScore();
                unionBarleyFeeOrder = unionBarleyFeeOrder + unionBarleyFee - tradeParamPo.getUnionBarleyFeeScore();
                platformPriceOrder = platformPriceOrder + platformPrice - tradeParamPo.getPlatformPriceScore();
                tradeInfos.addAll(tradeInfolist);
                linkerFeeOrder = linkerFeeOrder + linkerFee - tradeParamPo.getLinkerFeeScore();
                //交易手续费(平台抽成+联汇抽成)
                Integer processFee = platformFee;
                //推广佣金
                Integer spreadFee = 0;
                if (isSale) {
                    spreadFee = goodsTotalPrice - mallsGoodsTotalPrice;
                    //通联参数需要去掉反润佣金
                    spreadFeeOrder = spreadFeeOrder + spreadFee - profitFee;
                    spreadFeeTrade += spreadFee;
                }
                //反润佣金抵扣的金币
                Integer spreadFeeScore = 0;
                if (isSale && score > 0) {
                    //销售商小于供货商时
                    if ((spreadFee - profitFee) <= (income + incomeScore - (spreadFee - profitFee))) {
                        if ((spreadFee - profitFee) > 0 && incomeScore > 0) {
                            if ((spreadFee - profitFee) > incomeScore) {
                                spreadFeeScore = incomeScore;
                                spreadFeeOrder -= spreadFeeScore;
                                incomeScore = 0;
                            } else {
                                spreadFeeScore = (spreadFee - profitFee);
                                spreadFeeOrder -= spreadFeeScore;
                                incomeScore -= (spreadFee - profitFee);
                            }
                        }
                    } else {
                        //销售商大于供货商时
                        if ((income + incomeScore - (spreadFee - profitFee)) < incomeScore) {
                            //供货商收益小于商品收益的金币抵扣
                            spreadFeeScore = incomeScore - (income + incomeScore - (spreadFee - profitFee));
                            spreadFeeOrder -= spreadFeeScore;
                            incomeScore -= (spreadFee - profitFee);
                        }
                    }
                }
                incomeScoreOrder += incomeScore;
                spreadFeeScoreOrder += spreadFeeScore;
//                totalIncome = totalIncome + income - incomeScore;
                //之前的income已经去掉了金币
                totalIncome = totalIncome + income;
                totalIncomeScore = totalIncomeScore + incomeScore;
                //需要提供商品退款需要的记录
                //list深度拷贝
                List<Map<String, Object>> newList = copyList(tradeInfolist);
                goodsTradeInfos.addAll(newList);
                //获取商品收益，推广
                goodsTotalPriceOrder = goodsTotalPriceOrder + goodsTotalPrice;
                processFeeOrder = processFeeOrder + processFee;
                profitFeeOrder = profitFeeOrder + profitFee;
                this.getGoodsTrades(isSale, customerId, goodsTradeInfos, ifRebateToOrg, belongId, orgId, mallsOrgId, orderSn, recId, goodsTotalPrice, processFee, profitFee, mallsBelongId, spreadFee, "", incomeScore, spreadFeeScore);
            }
            orderName = orderName.replaceAll(",(.*)", "$1");
            if (((totalIncome + totalIncomeScore) - spreadFeeOrder) < 0) {
                isLoss = 1;
                mallsLossAmount = spreadFeeOrder - totalIncome;
                String lossOrgId = StringUtils.isEmpty(mallsBelongId) ? mallsOrgId : mallsBelongId;
                //订单更新
                purchaseProcessDao.updateLossOrder(isLoss, mallsLossAmount, salerLossAmount, orderSn, lossOrgId, null);
            }
            if (spreadFeeOrder + spreadFeeScoreOrder < 0) {
                isLoss = 1;
                salerLossAmount = 0 - spreadFeeOrder;
                String lossSalerOrgId = StringUtils.isEmpty(belongId) ? orgId : belongId;
                //订单更新
                purchaseProcessDao.updateLossOrder(isLoss, mallsLossAmount, salerLossAmount, orderSn, null, lossSalerOrgId);
            }
            //订单的trade
            this.getGoodsTrades(isSaleOrder, customerId, tradeInfos, ifRebateToOrg, belongId, orgId, mallsOrgId, orderSn, null, goodsTotalPriceOrder, processFeeOrder, profitFeeOrder, mallsBelongId, spreadFeeTrade, orderName, incomeScoreOrder, spreadFeeScoreOrder);
            //是否是知识付费
            for (Map<String, Object> tradeInfo : tradeInfos) {
                if (orderSn.equals(tradeInfo.get("orderSn"))) {
                    tradeInfo.put("orderName", orderName);
                    tradeInfo.put("isKnowledge", isKnowledge);
                    tradeInfo.put("isLoss", isLoss);
                }
            }
            for (Map<String, Object> tradeInfo : goodsTradeInfos) {
                if (orderSn.equals(tradeInfo.get("orderSn"))) {
                    tradeInfo.put("orderName", orderName);
                    tradeInfo.put("paySn", paySn);
                    tradeInfo.put("isKnowledge", isKnowledge);
                    tradeInfo.put("isLoss", isLoss);
                }
            }
            // 更新订单表实付金额(有金币时加)
//            if (allPay < goodsTotalPriceOrder || scoreOreder>0) {
//                purchaseProcessDao.updateOrderAmountByOrderSn(orderSn, allPay);
//            }
            totalPay = totalPay + allPay;
            if (payMode == 2 || payMode == 3) {
                //如果通联则创建请求通联参数
                TlResultPo tlResultPo = new TlResultPo(ifRfOrder, totalIncome, recomPriceOrder, sharePriceNormal, ifFwOrder, sharePriceOrder, linkerFeeOrder, unionBarleyFeeOrder, belongId, ifRebateToOrg, orderName, mallsBelongId, spreadFeeOrder, ifCzOrder, originalPriceOrder, platformPriceOrder, incomeScoreOrder,
                        recomPriceScoreOrder, sharePriceNormalScoreOrder, sharePriceScoreOrder, linkerFeeScoreOrder, unionBarleyFeeScoreOrder, spreadFeeScoreOrder, originalPriceScoreOrder, platformPriceScoreOrder, mallsOrgId, orderSn
                );
                tlResultList.add(tlResultPo);
            }
        }
        String result = "";
        if (payMode == 1) {
            //获取微信返回
            result = this.getResultWx(openid, paySn, totalPay, orgId, payType);
        } else if (payMode == 2 || payMode == 3) {
            //获取通联返回
            result = this.tlResult(tlResultList, orgId, totalPay, paySn, customerId, openid, payType, payMode, allScore, frontUrl);
        }
        // 单商品明细（退款和下发用）
        stringRedisTemplate.opsForValue().set(ACS_CREATE_GOODS_INFO + paySn, JSON.toJSONString(goodsTradeInfos), 30, TimeUnit.DAYS);
        //合并同一个订单平台费
        this.removeList(tradeInfos);
        // 分账数据
        stringRedisTemplate.opsForValue().set(ACS_CREATE_ORDER_INFO + paySn, JSON.toJSONString(tradeInfos), 30, TimeUnit.DAYS);
        // 签名数据
        stringRedisTemplate.opsForValue().set(ACS_CREATE_ORDER_RESULT + paySn, result, 60, TimeUnit.MINUTES);
        return result;
    }

    @Override
    public void getGoodsTrades(boolean isSale, String customerId, List<Map<String, Object>> goodsTradeInfos, boolean ifRebateToOrg, String belongId, String orgId, String mallsOrgId, String orderSn, Long recId, Integer goodsTotalPrice, Integer processFee, Integer profitFee, String mallsBelongId, Integer spreadFee, String orderName, Integer incomeScore, Integer spreadFeeScore) {
        // 单商品收益（退款和下发用）
        String from = customerId;
        String to = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? orgId : belongId;
        Integer tradeType = StringUtils.isEmpty(belongId) ? TradeTypeConstants.DEAL_PLATFORM_FEE : TradeTypeConstants.DEAL_FEE;
        Integer receiveRole = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? 1 : 2;
        Integer payRole = 5;
        if (!isSale) {
            //不是供销商商品
            // 单商品收益（退款和下发用）
            Map<String, Object> tradeInfo = this.setTradeInfo(from, orderSn, recId, to, goodsTotalPrice, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, incomeScore);
            goodsTradeInfos.add(tradeInfo);
            //交易手续费支出
            from = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? orgId : belongId;
            to = "";
            tradeType = TradeTypeConstants.TRADE_SERVER_FEE;
            receiveRole = -1;
            payRole = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? 1 : 2;
            Map<String, Object> tradeInfo2 = this.setTradeInfo(from, orderSn, recId, to, processFee, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, 0);
            goodsTradeInfos.add(tradeInfo2);
            tradeType = TradeTypeConstants.REJUVENATE_FEE;
            //返润佣金
            Map<String, Object> tradeInfo3 = this.setTradeInfo(from, orderSn, recId, to, profitFee, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, 0);
            goodsTradeInfos.add(tradeInfo3);
        } else {
            //供销商商品
            // 销货商商品收益
            Map<String, Object> tradeInfo = this.setTradeInfo(from, orderSn, recId, to, goodsTotalPrice, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, 0);
            goodsTradeInfos.add(tradeInfo);
            //销货商采购
            from = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? orgId : belongId;
            to = "";
            payRole = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? 1 : 2;
            tradeType = TradeTypeConstants.PURCHASE_FEE;
            receiveRole = -1;
            Map<String, Object> tradeInfo1 = this.setTradeInfo(from, orderSn, recId, to, goodsTotalPrice, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, 0);
            goodsTradeInfos.add(tradeInfo1);
            //推广佣金(包括供货商)
            from = StringUtils.isEmpty(mallsBelongId) ? mallsOrgId : mallsBelongId;
            to = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? orgId : belongId;
            tradeType = TradeTypeConstants.SPREAD_FEE;
            receiveRole = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? 1 : 2;
            payRole = StringUtils.isEmpty(mallsBelongId) ? 1 : 2;
            Map<String, Object> tradeInfo2 = this.setTradeInfo(from, orderSn, recId, to, spreadFee, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, spreadFeeScore);
            goodsTradeInfos.add(tradeInfo2);
            //返润佣金
            from = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? orgId : belongId;
            to = "";
            payRole = (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? 1 : 2;
            tradeType = TradeTypeConstants.REJUVENATE_FEE;
            receiveRole = -1;
            Map<String, Object> tradeInfo3 = this.setTradeInfo(from, orderSn, recId, to, profitFee, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, 0);
            goodsTradeInfos.add(tradeInfo3);


            // 供货商商品收益
            from = customerId;
            to = StringUtils.isEmpty(mallsBelongId) ? mallsOrgId : mallsBelongId;
            tradeType = StringUtils.isEmpty(mallsBelongId) ? TradeTypeConstants.DEAL_PLATFORM_FEE : TradeTypeConstants.DEAL_FEE;
            receiveRole = StringUtils.isEmpty(mallsBelongId) ? 1 : 2;
            payRole = 5;
            Map<String, Object> tradeInfo4 = this.setTradeInfo(from, orderSn, recId, to, goodsTotalPrice, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, incomeScore);
            goodsTradeInfos.add(tradeInfo4);

            //供货商交易手续费支出
            from = StringUtils.isEmpty(mallsBelongId) ? mallsOrgId : mallsBelongId;
            to = "";
            tradeType = TradeTypeConstants.TRADE_SERVER_FEE;
            receiveRole = -1;
            payRole = StringUtils.isEmpty(mallsBelongId) ? 1 : 2;
            Map<String, Object> tradeInfo5 = this.setTradeInfo(from, orderSn, recId, to, processFee, 1, tradeType, 1, receiveRole, payRole, "", orderName, false, 0);
            goodsTradeInfos.add(tradeInfo5);

        }

    }

    /**
     * trade插入记录
     *
     * @param from        支付用户
     * @param orderSn     订单号
     * @param recId       订单商品主键
     * @param to          收款用户
     * @param amount      金额（分）
     * @param expendType  支出类型
     * @param tradeType   交易类型
     * @param payType     支付方式
     * @param receiveRole 收款人角色
     * @return
     */
    @Override
    public Map<String, Object> setTradeInfo(String from, String orderSn, Long recId, String to, Integer amount, Integer expendType, Integer tradeType, Integer payType, Integer receiveRole, Integer payRole, String accountType, String orderName, Boolean isKnowledge, Integer incomeScore) {
        Map<String, Object> tradeInfo = new HashMap<>();
        tradeInfo.put("from", from);
        tradeInfo.put("orderName", orderName);
        tradeInfo.put("orderSn", orderSn);
        tradeInfo.put("isKnowledge", isKnowledge);
        tradeInfo.put("recId", recId);
        tradeInfo.put("to", to);
        tradeInfo.put("amount", amount);
        tradeInfo.put("score", incomeScore);
        tradeInfo.put("expendType", expendType);
        // 交易类型：0-提现，1-商品成交收益，2-商品服务费，3-商品推荐费，4-商品平台费，5-开通联盟商家平台费，6-开通联盟商家收益，7-开通加盟代理平台费，8-开通加盟代理收益，9-商城商品平台费，10-商城商品收益，11-提现手续费
        tradeInfo.put("tradeType", tradeType);
        // 支付方式1-rmb，2-积分
        tradeInfo.put("payType", payType);
        tradeInfo.put("receiveRole", receiveRole);
        tradeInfo.put("payRole", payRole);
        tradeInfo.put("accountType", accountType);
        return tradeInfo;
    }

    /**
     * 合并订单
     */
    @Override
    public List<Map<String, Object>> removeList(List<Map<String, Object>> tradeInfos) {
        List<Integer> removeIndex = new ArrayList<Integer>();
        for (int i = 0; i < tradeInfos.size(); i++) {
            Map<String, Object> tradeInfoi = tradeInfos.get(i);
            String tradeTypei = "";
            String orderSni = "";
            String payTypei = "";
            String fromi = "";
            String toi = "";
            int amounti = 0;
            int scorei = 0;
            if (!StringUtils.isEmpty(tradeInfoi.get("tradeType"))) {
                tradeTypei = tradeInfoi.get("tradeType").toString();
            }
            if (!StringUtils.isEmpty(tradeInfoi.get("orderSn"))) {
                orderSni = tradeInfoi.get("orderSn").toString();
            }
            if (!StringUtils.isEmpty(tradeInfoi.get("payType"))) {
                payTypei = tradeInfoi.get("payType").toString();
            }
            if (!StringUtils.isEmpty(tradeInfoi.get("from"))) {
                fromi = tradeInfoi.get("from").toString();
            }
            if (!StringUtils.isEmpty(tradeInfoi.get("to"))) {
                toi = tradeInfoi.get("to").toString();
            }
            if (!StringUtils.isEmpty(tradeInfoi.get("amount"))) {
                amounti = Integer.valueOf(tradeInfoi.get("amount").toString());
            }
            //合并联汇平台费和大麦平台费
            if ("4".equals(tradeTypei)) {
                for (int j = (tradeInfos.size() - 1); j > i; j--) {
                    Map<String, Object> tradeInfoj = tradeInfos.get(j);
                    String tradeTypej = tradeInfoj.get("tradeType").toString();
                    String orderSnj = tradeInfoj.get("orderSn").toString();
                    String payTypej = tradeInfoj.get("payType").toString();
                    String fromj = tradeInfoj.get("from").toString();
                    String toj = tradeInfoj.get("to").toString();
                    int amountj = Integer.valueOf(tradeInfoj.get("amount").toString());
                    if ("4".equals(tradeTypej) && orderSni.equals(orderSnj) && payTypei.equals(payTypej)
                            && fromi.equals(fromj) && toi.equals(toj)) {
                        amounti = amounti + amountj;
                        tradeInfoi.put("amount", amounti);
                        removeIndex.add(j);
                    }
                }
            }
            if ("9".equals(tradeTypei)) {
                for (int j = (tradeInfos.size() - 1); j > i; j--) {
                    Map<String, Object> tradeInfoj = tradeInfos.get(j);
                    String tradeTypej = tradeInfoj.get("tradeType").toString();
                    String orderSnj = tradeInfoj.get("orderSn").toString();
                    String payTypej = tradeInfoj.get("payType").toString();
                    String fromj = tradeInfoj.get("from").toString();
                    String toj = tradeInfoj.get("to").toString();
                    int amountj = Integer.valueOf(tradeInfoj.get("amount").toString());
                    if ("9".equals(tradeTypej) && orderSni.equals(orderSnj) && payTypei.equals(payTypej)
                            && fromi.equals(fromj) && toi.equals(toj)) {
                        amounti = amounti + amountj;
                        tradeInfoi.put("amount", amounti);
                        removeIndex.add(j);
                    }
                }
            }
            if ("19".equals(tradeTypei)) {
                for (int j = (tradeInfos.size() - 1); j > i; j--) {
                    Map<String, Object> tradeInfoj = tradeInfos.get(j);
                    String tradeTypej = tradeInfoj.get("tradeType").toString();
                    String orderSnj = tradeInfoj.get("orderSn").toString();
                    String payTypej = tradeInfoj.get("payType").toString();
                    String fromj = tradeInfoj.get("from").toString();
                    String toj = tradeInfoj.get("to").toString();
                    int amountj = Integer.valueOf(tradeInfoj.get("amount").toString());
                    if ("19".equals(tradeTypej) && orderSni.equals(orderSnj) && payTypei.equals(payTypej)
                            && fromi.equals(fromj) && toi.equals(toj)) {
                        amounti = amounti + amountj;
                        tradeInfoi.put("amount", amounti);
                        removeIndex.add(j);
                    }
                }
            }

        }
        List<Integer> newList = removeIndex.stream().distinct().collect(Collectors.toList());
        Collections.sort(newList);
        LOGGER.info("移除下标----》" + JSON.toJSONString(newList));
        LOGGER.info("tradeInfos个数----》" + tradeInfos.size());
        for (int i = (newList.size() - 1); i >= 0; i--) { //倒序
            if (newList.get(i) <= tradeInfos.size()) {
                int index = newList.get(i);
                tradeInfos.remove(index);
            }
        }
        return tradeInfos;
    }

    /**
     * 获取微信签名
     *
     * @param openid
     * @param paySn
     * @param totalPay
     * @param orgId
     * @return
     */
    @Override
    public String getResultWx(String openid, String paySn, int totalPay, String orgId, String payType) {
        String result = "";
        // 请求地址
        String url = wcPayProperties.getPayurl() + "/pay/wcpay";
        //支付网关请求封装参数
        Map<String, Object> req = this.getWxPayParam(openid, paySn, String.valueOf(totalPay), orgId, payType);
        // 请求支付网关
        try {
            // 积分抵扣后为0元
            if (totalPay != 0) {
                // 请求网关
                result = httpService.doPost(url, req);
                // 处理结果
                result = this.callResultProcessWx(result);
                stringRedisTemplate.opsForValue().set("orderType_" + paySn, "2", 1, TimeUnit.HOURS);
            }
        } catch (Exception e) {
            LOGGER.error("支付网关调用异常" + e);
            throw GlobalException.build("支付网关调用异常");
        }
        return result;
    }

    /**
     * 获取通联签名
     *
     * @param :            tlResultList 商品列表参数
     * @param ：orgId       机构id
     * @param ：paySn       合单订单号
     * @param ：allTotalPay 总金额
     * @param ：customerId  用户id
     * @param ：payType     支付类型 h5 小程序
     * @param ：payMode     支付模式 微信 通联 云听荟通联
     * @param ：score       总金币
     * @param ：frontUrl    支付后跳转地址
     * @param paySn
     * @param allTotalPay
     * @return
     */
    @Override
    public String tlResult(List<TlResultPo> tlResultList, String orgId, int allTotalPay, String paySn, String customerId, String openid, String payType, Integer payMode, Integer score, String frontUrl) {
        // 根据配置读取 服务费、推荐费、联汇抽成、大b抽成分别给谁
        List<Map<String, Object>> cashSplitItems = new ArrayList<>();
        List<Map<String, Object>> balanceSplitItems = new ArrayList<>();
        // 余额支出账户(现金分入账户，推荐费，服务费，大b抽成，联汇抽成)
        String feeId = this.getCustomerIdByFeeTypeAndOrdId(FeeConstants.SERVICE_FEE, orgId, payMode);
        String orgUid = stringRedisTemplate.opsForValue().get("orgUid:" + orgId);
        if (StringUtils.isEmpty(orgUid)) {
            orgUid = purchaseProcessDao.getAccountUidByOrgId(orgId);
            stringRedisTemplate.opsForValue().set("orgUid:" + orgId, orgUid);
        }
        Integer cashAmount = 0;
        Integer balanceAmount = 0;
        // 请求参数
        Map<String, Object> reqMap = new HashMap<>();
        String goodsName = "";
        for (TlResultPo tlResultPo : tlResultList) {
            //取消订单用
            List<Map<String, Object>> balanceOrderSplitItems = new ArrayList<>();
            LOGGER.info("给通联的对象参数----->" + JSON.toJSONString(tlResultPo));
            List<AccountInfo> subAccountList = new ArrayList<>();
            List<AccountInfo> balanceAccountList = new ArrayList<>();
            Map<String, Integer> subAccountMap = new HashMap<>();
            Map<String, Integer> subAccountMapg = new HashMap<>();
            String mallsOrgId = tlResultPo.getMallsOrgId();
            String mallsOrgUid = orgUid;
            if (!orgId.equals(mallsOrgId)) {
                mallsOrgUid = stringRedisTemplate.opsForValue().get("orgUid:" + mallsOrgId);
                if (StringUtils.isEmpty(mallsOrgUid)) {
                    mallsOrgUid = purchaseProcessDao.getAccountUidByOrgId(mallsOrgId);
                    stringRedisTemplate.opsForValue().set("orgUid:" + mallsOrgId, mallsOrgUid);
                }
            }
            Map<String, Integer> balanceAccountMap = new HashMap<>();
            Map<String, Integer> balanceAccountMapg = new HashMap<>();
            String orderSn = tlResultPo.getOrderSn();
            //是否有推荐费
            boolean ifRf = tlResultPo.getIfRf();
            //推荐费
            int recomPrice = tlResultPo.getRecomPrice();
            //商品收益
            int income = tlResultPo.getIncome();
            //金币服务费
            int sharePriceNormal = tlResultPo.getSharePriceNormal();
            //是否有服务费
            boolean ifFw = tlResultPo.getIfFw();
            //服务费
            int sharePrice = tlResultPo.getSharePrice();
            //推广费
            int spreadFee = tlResultPo.getSpreadFee();
            //联汇抽成
            int linkerFee = tlResultPo.getLinkerFee();
            //支付抽成
            int unionBarleyFee = tlResultPo.getUnionBarleyFee();
            //大b平台费
            int platformPrice = tlResultPo.getPlatformPrice();
            String belongId = tlResultPo.getBelongId();
            //是否是大b反润商品
            boolean ifRebateToOrg = tlResultPo.getIfRebateToOrg();
            //供货商belongId
            String mallsBelongId = tlResultPo.getMallsBelongId();
            //是否有创作费
            boolean ifCz = tlResultPo.getIfCz();
            //创作费
            int originalPrice = tlResultPo.getOriginalPrice();
            //商品收益金币抵扣
            int incomeScore = tlResultPo.getIncomeScore();
            //推荐费金币抵扣
            int recomPriceScore = tlResultPo.getRecomPriceScore();
            //服务费金币抵扣
            int sharePriceNormalScore = tlResultPo.getSharePriceNormalScore();
            //金币服务费的抵扣
            int sharePriceScore = tlResultPo.getSharePriceScore();
            //联汇抽成金币抵扣
            int linkerFeeScore = tlResultPo.getLinkerFeeScore();
            //支付抽成金币抵扣
            int unionBarleyFeeScore = tlResultPo.getUnionBarleyFeeScore();
            //推广费金币抵扣
            int spreadFeeScore = tlResultPo.getSpreadFeeScore();
            //创作费金币抵扣
            int originalPriceScore = tlResultPo.getOriginalPriceScore();
            //大b平台费金币抵扣
            int platformPriceScore = tlResultPo.getPlatformPriceScore();

            //订单名称
            String orderName = tlResultPo.getOrderName();
            goodsName = goodsName + " " + orderName;
            if (ifRf) {
                subAccountMap.put(FeeConstants.RECOMMEND_FEE, recomPrice);
                if (recomPriceScore > 0) {
                    balanceAccountMap.put(FeeConstants.RECOMMEND_FEE, recomPriceScore);
                }
            }
            if (ifFw) {
                if (sharePrice > 0) {
                    subAccountMap.put(FeeConstants.SERVICE_FEE, sharePrice);
                }
                if (sharePriceNormal > 0) {
                    subAccountMap.put(FeeConstants.SERVICE_COIN_FEE, sharePriceNormal);
                }
                if (sharePriceScore > 0) {
                    balanceAccountMap.put(FeeConstants.SERVICE_FEE, sharePriceScore);
                }
                if (sharePriceNormalScore > 0) {
                    balanceAccountMap.put(FeeConstants.SERVICE_COIN_FEE, sharePriceNormalScore);
                }
            }
            if (ifCz) {
                if (originalPrice > 0) {
                    subAccountMap.put(FeeConstants.ORIGINAL_FEE, originalPrice);
                }
                if (originalPriceScore > 0) {
                    balanceAccountMap.put(FeeConstants.ORIGINAL_FEE, originalPriceScore);
                }
            }
            subAccountMapg.put(FeeConstants.LINK_DRAW_FEE, linkerFee);
            subAccountMapg.put(FeeConstants.ORG_DRAW_FEE, unionBarleyFee);
            subAccountMap.put(FeeConstants.ORG_DRAW_FEE, platformPrice);
            if (linkerFeeScore > 0) {
                balanceAccountMapg.put(FeeConstants.LINK_DRAW_FEE, linkerFeeScore);
            }
            if (unionBarleyFeeScore > 0) {
                balanceAccountMapg.put(FeeConstants.ORG_DRAW_FEE, unionBarleyFeeScore);
            }
            if (platformPriceScore > 0) {
                balanceAccountMap.put(FeeConstants.ORG_DRAW_FEE, platformPriceScore);
            }
            for (String s : subAccountMap.keySet()) {
                subAccountList.add(this.getAccountMap(s, subAccountMap.get(s), orgId, payMode));
            }
            for (String s : subAccountMapg.keySet()) {
                subAccountList.add(this.getAccountMap(s, subAccountMapg.get(s), mallsOrgId, payMode));
            }
            for (String s : balanceAccountMap.keySet()) {
                balanceAccountList.add(this.getAccountMap(s, balanceAccountMap.get(s), orgId, payMode));
            }
            for (String s : balanceAccountMapg.keySet()) {
                balanceAccountList.add(this.getAccountMap(s, balanceAccountMapg.get(s), mallsOrgId, payMode));
            }
            Map<String, Integer> collect = subAccountList.stream()
                    .collect(Collectors.groupingBy(AccountInfo::getCustomerId, Collectors.summingInt(AccountInfo::getAmount)));
            Map<String, Integer> collectb = balanceAccountList.stream()
                    .collect(Collectors.groupingBy(AccountInfo::getCustomerId, Collectors.summingInt(AccountInfo::getAmount)));
            // belongId = purchaseProcessDao.getBelongIdByGoodsId(id);
            // 是否为大b需要反润的商品(1.11新增)
            // 小b和大b要去查uid
            String belongUid = "";
            if (!StringUtils.isEmpty(belongId)) {
                belongUid = stringRedisTemplate.opsForValue().get("belongUid:" + belongId);
                if (StringUtils.isEmpty(belongUid)) {
                    belongUid = purchaseProcessDao.getAccountUidByCustomerId(belongId);
                    stringRedisTemplate.opsForValue().set("belongUid:" + belongId, belongUid);
                }
            }
            income = income - spreadFee;
            String mallsBelongUid = "";
            if (!StringUtils.isEmpty(mallsBelongId)) {
                mallsBelongUid = stringRedisTemplate.opsForValue().get("belongUid:" + mallsBelongId);
                if (StringUtils.isEmpty(mallsBelongUid)) {
                    mallsBelongUid = purchaseProcessDao.getAccountUidByCustomerId(mallsBelongId);
                    stringRedisTemplate.opsForValue().set("belongUid:" + mallsBelongId, mallsBelongUid);
                }
            }
            // 每个机构一个联汇子账号
            String linkId = "";
            if (payMode == 2) {
                linkId = stringRedisTemplate.opsForValue().get("linkIdType:orgId_" + mallsOrgId);
                if (StringUtils.isEmpty(linkId)) {
                    linkId = purchaseProcessDao.getLinkIdByOrgId(mallsOrgId);
                    stringRedisTemplate.opsForValue().set("linkIdType:orgId_" + mallsOrgId, linkId);
                }
            } else if (payMode == 3) {
                linkId = stringRedisTemplate.opsForValue().get("linkIdType:orgId_linker");
                if (StringUtils.isEmpty(linkId)) {
                    linkId = purchaseProcessDao.getLinkIdByLinkOrg("linker");
                    stringRedisTemplate.opsForValue().set("linkIdType:orgId_linker", linkId);
                }
            }

            if (StringUtils.isEmpty(linkId)) {
                throw GlobalException.build("联汇子账号暂未绑定");
            }

            if (income > 0) {
                //销售商亏损
                if (spreadFee < 0) {
                    income += spreadFee;
                }
                Map<String, Object> cashSplitItem1 = new HashMap<>();
                if (StringUtils.isEmpty(mallsBelongId) && (StringUtils.isEmpty(mallsOrgId))) {
                    cashSplitItem1.put("customerId", StringUtils.isEmpty(belongId) ? orgUid : belongUid);
                    cashSplitItem1.put("type", StringUtils.isEmpty(belongId) ? 1 : 0);
                } else {
                    cashSplitItem1.put("customerId", StringUtils.isEmpty(mallsBelongId) ? mallsOrgUid : mallsBelongUid);
                    cashSplitItem1.put("type", (orgId.equals(mallsOrgId) && StringUtils.isEmpty(mallsBelongId) ? 1 : 0));
                }
                cashSplitItem1.put("splitAmount", income);
                cashSplitItem1.put("note", "商品收益");
                cashSplitItem1.put("orderId", paySn);
                cashSplitItems.add(cashSplitItem1);
            }
            if (incomeScore > 0) {
                Map<String, Object> balanceSplitItem1 = new HashMap<>();
                balanceSplitItem1.put("customerId", StringUtils.isEmpty(mallsBelongId) ? mallsOrgUid : mallsBelongUid);
                balanceSplitItem1.put("type", 0);
                balanceSplitItem1.put("splitAmount", incomeScore);
                balanceSplitItem1.put("note", "金币商品收益");
                balanceSplitItem1.put("orderId", paySn);
                balanceSplitItems.add(balanceSplitItem1);
                //取消订单用
                Map<String, Object> balanceSplitItemt = new HashMap<>();
                balanceSplitItemt.put("amount", incomeScore);
                balanceSplitItemt.put("bizUserId", StringUtils.isEmpty(mallsBelongId) ? mallsOrgUid : mallsBelongUid);
                balanceOrderSplitItems.add(balanceSplitItemt);
            }
            if (spreadFee > 0) {
                //供货商亏损
                if (income < 0) {
                    spreadFee += income;
                }
                Map<String, Object> cashSplitItem1 = new HashMap<>();
                cashSplitItem1.put("customerId", StringUtils.isEmpty(belongId) ? orgUid : belongUid);
                cashSplitItem1.put("type", StringUtils.isEmpty(belongId) ? 1 : 0);
                cashSplitItem1.put("splitAmount", spreadFee);
                cashSplitItem1.put("note", "推广佣金");
                cashSplitItem1.put("orderId", paySn);
                cashSplitItems.add(cashSplitItem1);
            }
            if (spreadFeeScore > 0) {
                Map<String, Object> balanceSplitItem1 = new HashMap<>();
                balanceSplitItem1.put("customerId", StringUtils.isEmpty(belongId) ? orgUid : belongUid);
                balanceSplitItem1.put("type", StringUtils.isEmpty(belongId) ? 1 : 0);
                balanceSplitItem1.put("splitAmount", spreadFeeScore);
                balanceSplitItem1.put("note", "金币推广佣金");
                balanceSplitItem1.put("orderId", paySn);
                balanceSplitItems.add(balanceSplitItem1);
                //取消订单用
                Map<String, Object> balanceSplitItemt = new HashMap<>();
                balanceSplitItemt.put("amount", spreadFeeScore);
                balanceSplitItemt.put("bizUserId", StringUtils.isEmpty(belongId) ? orgUid : belongUid);
                balanceOrderSplitItems.add(balanceSplitItemt);
            }
            // 用户钱到lh
            String endOrgUid = orgUid;
            collect.forEach((x, y) -> {
                if (y > 0) {
                    Map<String, Object> cashSplitItem = new HashMap<>();
                    cashSplitItem.put("customerId", x);
                    cashSplitItem.put("splitAmount", y);
                    cashSplitItem.put("note", "商品收益-平台费");
                    cashSplitItem.put("orderId", paySn);
                    if (endOrgUid.equals(x)) {
                        cashSplitItem.put("type", 1);
                    } else {
                        cashSplitItem.put("type", 0);
                    }
                    cashSplitItems.add(cashSplitItem);
                }
            });

            collectb.forEach((x, y) -> {
                if (y > 0) {
                    if (!"#yunBizUserId_B2C#".equals(x)) {
                        Map<String, Object> balanceSplitItem = new HashMap<>();
                        balanceSplitItem.put("customerId", x);
                        balanceSplitItem.put("splitAmount", y);
                        balanceSplitItem.put("note", "商品收益-平台费");
                        balanceSplitItem.put("orderId", paySn);
                        if (endOrgUid.equals(x)) {
                            balanceSplitItem.put("type", 1);
                        } else {
                            balanceSplitItem.put("type", 0);
                        }
                        balanceSplitItems.add(balanceSplitItem);
                        //取消订单用
                        Map<String, Object> balanceSplitItemt = new HashMap<>();
                        balanceSplitItemt.put("amount", y);
                        balanceSplitItemt.put("bizUserId", x);
                        balanceOrderSplitItems.add(balanceSplitItemt);
                    }
                }
            });
            if (balanceOrderSplitItems.size() > 0) {
                //缓存用于退款
                stringRedisTemplate.opsForValue().set(CANCEL_SCORE_ORDER + orderSn, JSON.toJSONString(balanceOrderSplitItems), 1, TimeUnit.HOURS);
            }
        }

        String caCustomerId = "";
        for (Map<String, Object> cashSplitItemA : cashSplitItems) {
            Integer amount = 0;
            if (!StringUtils.isEmpty(cashSplitItemA.get("splitAmount"))) {
                amount = (Integer) cashSplitItemA.get("splitAmount");
            }
            cashAmount = cashAmount + amount;
            if (orgUid.equals(cashSplitItemA.get("customerId"))) {
                caCustomerId = orgUid;
            }
        }
        if (StringUtils.isEmpty(caCustomerId) && cashSplitItems.size() > 0) {
            Map<String, Object> cashSplitItem = new HashMap<>();
            cashSplitItem.put("customerId", orgUid);
            cashSplitItem.put("splitAmount", 0);
            cashSplitItem.put("note", "用于下发余额账户");
            cashSplitItem.put("orderId", paySn);
            cashSplitItem.put("type", 1);
            cashSplitItems.add(cashSplitItem);
        }
        // 现金支付金额
        reqMap.put("cashAmount", cashAmount);
        // 现金分账明细，JSON字符串
        if (cashSplitItems.size() > 0) {
            reqMap.put("cashSplitItems", JSON.toJSONString(cashSplitItems));
        }
        if (score > 0) {
            // 金币分账明细，JSON字符串
            if (balanceSplitItems.size() > 0) {
                reqMap.put("balanceSplitItems", JSON.toJSONString(balanceSplitItems));
                for (Map<String, Object> balanceSplitItemA : balanceSplitItems) {
                    Integer scoreA = 0;
                    if (!StringUtils.isEmpty(balanceSplitItemA.get("splitAmount"))) {
                        scoreA = (Integer) balanceSplitItemA.get("splitAmount");
                    }
                    balanceAmount = balanceAmount + scoreA;
                }
                reqMap.put("balanceAmount", balanceAmount);
            }

        }
        if (cashAmount == 0 && score == 0) {
            return "";
        }
        // 收款人id 收款人银行账号 金额 备注 订单sn
        // 支付后跳转地址
        reqMap.put("frontUrl", frontUrl);
        // 支付用户ID
        reqMap.put("customerId", customerId);
        // 商品描述
        if (goodsName.length() > 40) {
            goodsName = goodsName.substring(0, 40);
        }
        reqMap.put("goodsName", goodsName);
        // 支付用户OPENID
        reqMap.put("openID", openid);
        // 平台订单ID
        reqMap.put("orderSn", paySn);
        // 收款用户帐号(收款用户为机构会员时必填，机构结算标识)(大b账号)
//      reqMap.put("payeeAccountNumber", orgAccountNumber);
        // 收款用户ID
        reqMap.put("payeeUserID", orgUid);
        // 余额支出账户
        reqMap.put("feeCustomerId", feeId);
        // 应用appId
        String appId = "";
        if ("WX".equals(payType)) {
            if (payMode == 2) {
                appId = stringRedisTemplate.opsForValue().get("appIdWX:_orgId_" + orgId);
                if (StringUtils.isEmpty(appId)) {
                    appId = purchaseProcessDao.getAppIdByOrgId(orgId);
                    stringRedisTemplate.opsForValue().set("appIdWX:_orgId_" + orgId, appId);
                }
            } else if (payMode == 3) {
                appId = stringRedisTemplate.opsForValue().get("appIdWX:_orgId_linker");
                if (StringUtils.isEmpty(appId)) {
                    appId = purchaseProcessDao.getAppIdByOrgId("linker");
                    stringRedisTemplate.opsForValue().set("appIdWX:_orgId_linker", appId);
                }
            }
        } else if ("XCX".equals(payType)) {
            appId = stringRedisTemplate.opsForValue().get("appIdXCX:orgId_" + orgId);
            if (StringUtils.isEmpty(appId)) {
                appId = purchaseProcessDao.getXcxAppIdByOrgId(orgId);
                if (!StringUtils.isEmpty(appId)) {
                    stringRedisTemplate.opsForValue().set("appIdXCX:orgId_" + orgId, appId);
                }
            }
        }
        if (StringUtils.isEmpty(appId)) {
            throw GlobalException.build("appId获取失败");
        }
        reqMap.put("appId", appId);
        // 行业代码
        String industryCode = purchaseProcessDao.getOrgMerchantInfoByOrgId(orgId);
        reqMap.put("industryCode", industryCode);
        // 行业名称
        String industryName = purchaseProcessDao.getIndustryNameByCode(industryCode);
        reqMap.put("industryName", industryName);
        // 支付方式：WX-公众号支付；XCX-微信小程序支付
        reqMap.put("payType", payType);
        // 访问终端类型:1手机；2PC
        reqMap.put("source", 1);
        // 交易验证方式：0-无验证；1-短信验证码；2-支付密码
        reqMap.put("validateType", 0);
        // 测试环境用yt
        String alias = "";
        if (payMode == 3) {
            alias = stringRedisTemplate.opsForValue().get("alias:orgId_linker");
            if (StringUtils.isEmpty(alias)) {
                alias = maiBaoLaService.getAliasByLinker();
                stringRedisTemplate.opsForValue().set("alias:orgId_linker", alias);
            }
        }
        if (payMode == 2) {
            alias = stringRedisTemplate.opsForValue().get("alias:orgId_" + orgId);
            if (StringUtils.isEmpty(alias)) {
                alias = maiBaoLaService.getAlias(orgId);
                stringRedisTemplate.opsForValue().set("alias:orgId_" + orgId, alias);
            }
        }
        reqMap.put("clintType", alias);
        // 手续费
        reqMap.put("fee", 0);
        String url = wcPayProperties.getAcsurl() + WcPayConstant.TRADE_PAY_ORDER;
        // 请求支付网关
        String result = "";
        try {
            LOGGER.info("通联支付请求参数==={}", JSON.toJSONString(reqMap));
            result = httpService.doPost(url, JSON.toJSONString(reqMap), WcPayConstant.JSON);
            result = this.callResultProcess(result);
            stringRedisTemplate.opsForValue().set("orderType_" + paySn, "2", 1, TimeUnit.HOURS);
        } catch (Exception e) {
            LOGGER.error("支付网关调用异常", e);
            throw GlobalException.build("支付网关调用异常");
        }
        return result;
    }

    /**
     * 获取需要插入的trade数据
     *
     * @param ifFw            是否产出服务费给分享人
     * @param distributor     分享人id
     * @param :score          抵扣积分（金币）
     * @param customerId      购买人id
     * @param ifRebateToOrg   是否为大b需要反润的商品
     * @param orgId           机构id
     * @param belongId        商品所属人id
     * @param ifRf            是否产出推荐费给推荐人
     * @param :sharePrice     返利值(服务费)1
     * @param :recomPrice     返利值(推荐费)2
     * @param pid             上级id
     * @param unhappen        未产生费用给谁 1-商家2-机构
     * @param :income         商品收益=订单总金额-总返利-平台费4
     * @param :unionBarleyFee 大麦抽成
     * @param :platformPrice  返利值(平台费)3
     * @param :linkerFee      联汇抽成
     * @param linkId          联汇id
     * @param ifCz            是否有创作费
     * @param author          创作人
     * @param :originalPrice  创作费
     */
    @Override
    public Map getTradeInfo(TradeParamPo po, boolean ifFw, String distributor, String distributorFw, String customerId, boolean ifRebateToOrg, String mallsOrgId,
                            String belongId, boolean ifRf, String pid, Integer unhappen,
                            String linkId, String orderSn, Long recId, boolean distributorIsNormal, boolean ifCz, String author, String orgId) {
        LOGGER.info("系统分钱参数 ifFw----> " + ifFw
                + " distributor----> " + distributor
                + " distributorFw----> " + distributorFw
                + " customerId----> " + customerId
                + " ifRebateToOrg----> " + ifRebateToOrg
                + " orgId----> " + orgId
                + " belongId----> " + belongId
                + " ifRf----> " + ifRf
                + " pid----> " + pid
                + " unhappen----> " + unhappen
                + " linkId----> " + linkId
                + " orderSn----> " + orderSn
                + " recId----> " + recId
                + " ifCz----> " + ifCz
                + " author----> " + author
        );
        LOGGER.info(JSON.toJSONString(po));
        Integer income = po.getIncome();
        Integer score = po.getScore();
        Integer sharePrice = po.getSharePrice();
        Integer recomPrice = po.getRecomPrice();
        Integer originalPrice = po.getOriginalPrice();
        Integer platformPrice = po.getPlatformPrice();
        Integer linkerFee = po.getLinkerFee();
        Integer unionBarleyFee = po.getUnionBarleyFee();
        Integer unhappenFee = 0;
        if (ifFw && !ifRf && !ifCz) {
            unhappenFee += recomPrice + originalPrice;
            po.setRecomPrice(0);
            po.setOriginalPrice(0);
        } else if (!ifFw && ifRf && !ifCz) {
            unhappenFee += sharePrice + originalPrice;
            po.setSharePrice(0);
            po.setOriginalPrice(0);
        } else if (!ifFw && !ifRf && ifCz) {
            unhappenFee += sharePrice + recomPrice;
            po.setSharePrice(0);
            po.setRecomPrice(0);
        } else if (!ifFw && ifRf && ifCz) {
            unhappenFee += sharePrice;
            po.setSharePrice(0);
        } else if (ifFw && !ifRf && ifCz) {
            unhappenFee += recomPrice;
            po.setRecomPrice(0);
        } else if (ifFw && ifRf && !ifCz) {
            unhappenFee += originalPrice;
            po.setOriginalPrice(0);
        } else if (!ifFw && !ifRf && !ifCz) {
            unhappenFee += sharePrice + recomPrice + originalPrice;
            po.setOriginalPrice(0);
            po.setRecomPrice(0);
            po.setSharePrice(0);
        }
        if (unhappen == 1) {
            // 未产生费用给商家
            income += unhappenFee;
            po.setIncome(income);
        } else if (unhappen == 2 && unhappenFee > 0) {
            // 未产生费用给平台
            platformPrice += unhappenFee;
            po.setPlatformPrice(platformPrice);
        }
        LOGGER.info("金币抵扣前" + JSON.toJSONString(po));
        //算出金币抵扣
        if (score != null && score > 0) {
            po = this.getEndTrade(po);
        }
        LOGGER.info("金币抵扣后" + JSON.toJSONString(po));
        // 系统内分钱
        List<Map<String, Object>> tradeInfos = new ArrayList<>();
        if (po.getScore() != 0) {
            // 积分支出
            // 以后可以改为构造器 new TradeInfo(args...);
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", customerId);
            tradeInfo.put("orderSn", orderSn);
            tradeInfo.put("recId", recId);
            tradeInfo.put("to", (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? orgId : belongId);
            tradeInfo.put("amount", score);
            tradeInfo.put("tradeType", TradeTypeConstants.DEAL_SCORE);
            tradeInfo.put("payType", 2);
            tradeInfo.put("receiveRole", (ifRebateToOrg || StringUtils.isEmpty(belongId)) ? 1 : 2);
            tradeInfos.add(tradeInfo);

        }
        // 组装、获取各账号的账号类型：ABC，和账户id
        String serviceAccountType = "";
        String serviceAccount = "";
        String recommendAccountType = "";
        String recommendAccount = "";
        String orgDrawAccountType = "";
        String orgDrawAccount = "";
        String linkDrawAccountType = "";
        String linkDrawAccount = "";
        if (ifFw && ifRf) {
            // 服务
            Map<String, Object> tradeInfo1 = new HashMap<>();
            tradeInfo1.put("from", customerId);
            tradeInfo1.put("orderSn", orderSn);
            tradeInfo1.put("recId", recId);
            tradeInfo1.put("to", distributorFw);
            tradeInfo1.put("amount", sharePrice);
            tradeInfo1.put("score", po.getSharePriceScore());
            // 积分交易类型0-金币抵扣，1-商品服务费，2 -金币退回
            tradeInfo1.put("tradeType", distributorIsNormal ? TradeTypeConstants.SERVER_SCORE : TradeTypeConstants.SERVER_FEE);
            // 支付方式1-rmb，2-积分
            tradeInfo1.put("payType", distributorIsNormal ? 2 : 1);
            tradeInfo1.put("receiveRole", 5);
            tradeInfo1.put("accountType", serviceAccountType);
            tradeInfo1.put("receiveAccount", serviceAccount);
            tradeInfos.add(tradeInfo1);
            // 推荐
            Map<String, Object> tradeInfo2 = new HashMap<>();
            tradeInfo2.put("from", customerId);
            tradeInfo2.put("orderSn", orderSn);
            tradeInfo2.put("recId", recId);
            tradeInfo2.put("to", pid);
            tradeInfo2.put("amount", recomPrice);
            tradeInfo2.put("score", po.getRecomPriceScore());
            // 交易类型：0-提现，1-商品成交收益，2-商品服务费，3-商品推荐费，4-商品平台费，5-开通联盟商家平台费，6-开通联盟商家收益，7-开通加盟代理平台费，8-开通加盟代理收益，9-商城商品平台费，10-商城商品收益，11-提现手续费
            tradeInfo2.put("tradeType", TradeTypeConstants.RECOMMENDS_FEE);
            tradeInfo2.put("payType", 1);
            tradeInfo2.put("receiveRole", 5);
            tradeInfo2.put("accountType", recommendAccountType);
            tradeInfo2.put("receiveAccount", recommendAccount);
            tradeInfos.add(tradeInfo2);
        } else if (ifFw) {
            // 仅服务费
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", customerId);
            tradeInfo.put("orderSn", orderSn);
            tradeInfo.put("recId", recId);
            tradeInfo.put("to", distributorFw);
            tradeInfo.put("amount", sharePrice);
            tradeInfo.put("score", po.getSharePriceScore());
            tradeInfo.put("tradeType", distributorIsNormal ? TradeTypeConstants.SERVER_SCORE : TradeTypeConstants.SERVER_FEE);
            tradeInfo.put("payType", distributorIsNormal ? 2 : 1);
            tradeInfo.put("receiveRole", 5);
            tradeInfo.put("accountType", serviceAccountType);
            tradeInfo.put("receiveAccount", serviceAccount);
            tradeInfos.add(tradeInfo);
        } else if (ifRf) {
            // 仅推荐费
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", customerId);
            tradeInfo.put("orderSn", orderSn);
            tradeInfo.put("recId", recId);
            tradeInfo.put("to", pid);
            tradeInfo.put("amount", recomPrice);
            tradeInfo.put("score", po.getRecomPriceScore());
            tradeInfo.put("tradeType", TradeTypeConstants.RECOMMENDS_FEE);
            tradeInfo.put("payType", 1);
            tradeInfo.put("receiveRole", 5);
            tradeInfo.put("accountType", recommendAccountType);
            tradeInfo.put("receiveAccount", recommendAccount);
            tradeInfos.add(tradeInfo);
        }

        if (ifCz) {
            // 创作费
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", customerId);
            tradeInfo.put("orderSn", orderSn);
            tradeInfo.put("recId", recId);
            tradeInfo.put("to", author);
            tradeInfo.put("amount", originalPrice);
            tradeInfo.put("score", po.getOriginalPriceScore());
            tradeInfo.put("tradeType", TradeTypeConstants.CREATE_FEE);
            tradeInfo.put("payType", 1);
            tradeInfo.put("receiveRole", 5);
            tradeInfo.put("accountType", recommendAccountType);
            tradeInfo.put("receiveAccount", recommendAccount);
            tradeInfos.add(tradeInfo);
        }

        if (platformPrice != 0) {
            // 大b平台费
            Map<String, Object> tradeInfo1 = new HashMap<>();
            tradeInfo1.put("from", customerId);
            tradeInfo1.put("orderSn", orderSn);
            tradeInfo1.put("recId", recId);
            tradeInfo1.put("to", orgId);
            tradeInfo1.put("amount", platformPrice);
            tradeInfo1.put("score", po.getPlatformPriceScore());
            tradeInfo1.put("tradeType", TradeTypeConstants.GOODS_PLATFORM_FEE);
            tradeInfo1.put("payType", 1);
            tradeInfo1.put("receiveRole", 1);
            tradeInfo1.put("accountType", orgDrawAccountType);
            tradeInfo1.put("receiveAccount", orgDrawAccount);
            tradeInfos.add(tradeInfo1);
        }
        if (linkerFee != 0) {
            // 联汇抽成
            Map<String, Object> tradeInfo2 = new HashMap<>();
            tradeInfo2.put("from", customerId);
            tradeInfo2.put("to", linkId);
            tradeInfo2.put("orderSn", orderSn);
            tradeInfo2.put("recId", recId);
            tradeInfo2.put("amount", linkerFee);
            tradeInfo2.put("score", po.getLinkerFeeScore());
            tradeInfo2.put("tradeType", TradeTypeConstants.GOODS_LINK_PLATFORM_FEE);
            tradeInfo2.put("payType", 1);
            tradeInfo2.put("receiveRole", 0);
            tradeInfo2.put("accountType", linkDrawAccountType);
            tradeInfo2.put("receiveAccount", linkDrawAccount);
            tradeInfos.add(tradeInfo2);
        }
        if (unionBarleyFee != 0) {
            // 支付抽成(大b)
            Map<String, Object> tradeInfo3 = new HashMap<>();
            tradeInfo3.put("from", customerId);
            tradeInfo3.put("orderSn", orderSn);
            tradeInfo3.put("recId", recId);
            tradeInfo3.put("to", mallsOrgId);
            tradeInfo3.put("amount", unionBarleyFee);
            tradeInfo3.put("score", po.getUnionBarleyFeeScore());
            tradeInfo3.put("tradeType", TradeTypeConstants.PAY_CENTAGE_FEE);
            tradeInfo3.put("payType", 1);
            tradeInfo3.put("receiveRole", 1);
            tradeInfo3.put("accountType", orgDrawAccountType);
            tradeInfo3.put("receiveAccount", orgDrawAccount);
            tradeInfos.add(tradeInfo3);
        }
        Map map = new HashMap();
        map.put("tradeInfos", tradeInfos);
        map.put("tradeParamPo", po);
        map.put("unhappenFee", unhappenFee);
        return map;
    }

    @Override
    public TradeParamPo getEndTrade(TradeParamPo po) {
        Integer score = po.getScore();
        Integer sharePrice = po.getSharePrice();
        Integer originalPrice = po.getOriginalPrice();
        Integer recomPrice = po.getRecomPrice();
        Integer unionBarleyFee = po.getUnionBarleyFee();
        Integer platformPrice = po.getPlatformPrice();
        Integer linkerFee = po.getLinkerFee();
        Integer income = po.getIncome();
        Map<String, Integer> map = new LinkedHashMap();
        //按照这种顺序put 服务费励<创作奖励<推荐费<支付抽成（联汇）<支付抽成（大麦）<平台抽成<商品成交收益
        map.put("sharePrice", sharePrice);
        map.put("originalPrice", originalPrice);
        map.put("recomPrice", recomPrice);
        map.put("linkerFee", linkerFee);
        map.put("unionBarleyFee", unionBarleyFee);
        map.put("platformPrice", platformPrice);
        map.put("income", income);
        //从小到大排序
        map = MapSortUtil.sortAscend(map);
        for (Object t : map.keySet()) {
            Integer amount = map.get(t.toString());
            if (amount > score) {
                amount = amount - score;
                score = 0;
            } else {
                score = score - amount;
                amount = 0;
            }
            map.put(t.toString(), amount);
        }
        po.setSharePrice(map.get("sharePrice"));
        po.setSharePriceScore(sharePrice - map.get("sharePrice"));
        po.setOriginalPrice(map.get("originalPrice"));
        po.setOriginalPriceScore(originalPrice - map.get("originalPrice"));
        po.setRecomPrice(map.get("recomPrice"));
        po.setRecomPriceScore(recomPrice - map.get("recomPrice"));
        po.setUnionBarleyFee(unionBarleyFee);
        po.setUnionBarleyFeeScore(unionBarleyFee - map.get("unionBarleyFee"));
        po.setPlatformPrice(platformPrice);
        po.setPlatformPriceScore(platformPrice - map.get("platformPrice"));
        po.setLinkerFee(linkerFee);
        po.setLinkerFeeScore(linkerFee - map.get("linkerFee"));
        po.setIncome(map.get("income"));
        po.setIncomeScore(income - map.get("income"));
        return po;
    }

    /**
     * 生成微信支付调用参数
     */
    @Override
    public Map<String, Object> getWxPayParam(String openId, String orderSn, String totalFee, String orgId, String payType) {
        String notifyUrl = systemProperties.getScrmUrl() + "acs/paycallbackforwx";
        String wcpayType = "STEPLINK_" + orgId;
        if ("WX".equals(payType)) {
            wcpayType = "STEPLINK_" + orgId;
        } else if ("XCX".equals(payType)) {
            wcpayType = "STEPLINK_XCX_" + orgId;
        }
        Map<String, String> params = new HashMap<>();
        params.put("body", "step商城订单");
        params.put("notifyUrl", notifyUrl);
        params.put("openid", openId);
        params.put("outTradeNo", orderSn);
        params.put("timestamp", String.valueOf(System.currentTimeMillis()));
        params.put("totalFee", totalFee);
        params.put("tradeType", "JSAPI");
        params.put("wcpayType", wcpayType);
        if (systemProperties.isWxSplit()) {
            params.put("needShare", "1");
        }
        Map<String, String> appSign = ParamSignUtils.sign(params);
        params.put("appSign", appSign.get("appSign"));
        LOGGER.info("paymsg=================" + params);
        return new HashMap<>(params);
    }

    /**
     * 调用结果处理(中金)
     */
    @Override
    public String callResultProcess(String result) throws GlobalException {
        if (StringUtils.isEmpty(result)) {
            throw GlobalException.build("网关调用失败");
        }
        LOGGER.info(result);
        Map resMap = (Map) JSON.parse(result);
        if (!resMap.containsKey("code")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        if (!"200".equals(resMap.get("code"))) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        if (!resMap.containsKey("data")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        Map data = (Map) resMap.get("data");
        if (!data.containsKey("authCode")) {
            throw GlobalException.build("网关调用失败:" + resMap.get("msg"));
        }
        return (String) data.get("authCode");
    }

    /**
     * 调用结果处理(微信)
     */
    @Override
    public String callResultProcessWx(String result) throws GlobalException {
        if (StringUtils.isEmpty(result)) {
            throw GlobalException.build("操作失败");
        }
        LOGGER.info(result);
        Object parse = JSON.parse(result);
        Map ret = (Map) parse;
        if ((Integer) ret.get("rt") != 1) {
            throw GlobalException.build("支付网关调用失败");
        }
        //noinspection unchecked
        Map<String, Object> retInfo = (Map) ret.get("object");
        retInfo.put("package", "prepay_id=" + retInfo.get("prepayId"));
        return JSON.toJSONString(retInfo);
    }

    /**
     * 根据用户id判断是否为普通用户(需要分金币的用户)
     */
    @Override
    public boolean getUserRole(String customerId) {
//        Integer role = purchaseProcessDao.getUserRoleByCustomerId(customerId);
        Map<String, Long> role = purchaseProcessDao.getUserRoleMapByCustomerId(customerId);
        Long a = role.get("a");
        Long b = role.get("b");
        Long c = role.get("c");
        return c != 1;
    }

    private void updateExerciseRecord(Map<String, Object> map, String customerId) {
        // 更新状态
        purchaseProcessDao.updateExerciseRecordByRecId(map);
        // 判断赠品中是否有懂小姐体检券
        Integer integer = purchaseProcessDao.countDongExerciseRecordByRecId(map);
        if (integer > 0) {
            // 懂小姐
            String url = systemProperties.getDongUrl() + DongConstant.USER_GOODS_GIVE_COUPONS;
            Map<String, Object> reqMap = new HashMap<>();
            reqMap.put("couponType", "3");
            reqMap.put("orderId", map.get("orderId"));
            reqMap.put("userId", customerId);
            String result = "";
            LOGGER.info("exercise===req[{}]===url[{}]", JSON.toJSONString(reqMap), url);
            try {
                result = httpService.doPost(url, reqMap);
            } catch (URISyntaxException | IOException e) {
                LOGGER.error("懂小姐接口调用异常");
            }
            LOGGER.info("exercise===res[{}]", result);
        }
    }

    /**
     * 根据机构和费用类型查询分账配置账号id
     *
     * @param type  见FeeConstants
     * @param orgId 机构id
     */
    @Override
    public String getCustomerIdByFeeTypeAndOrdId(String type, String orgId, Integer payMode) throws GlobalException {

        String account = stringRedisTemplate.opsForValue().get("accountType:type_" + type + "orgId_" + orgId);
        if (StringUtils.isEmpty(account)) {
            account = purchaseProcessDao.getAccountByFeeTypeAndOrdId(type, orgId);
            if (StringUtils.isEmpty(account)) {
                purchaseProcessDao.insertAcsOrgDefaultConfig(orgId);
                account = purchaseProcessDao.getAccountByFeeTypeAndOrdId(type, orgId);
            }
            stringRedisTemplate.opsForValue().set("accountType:type_" + type + "_orgId_" + orgId, account);
        }
        switch (account) {
            case "A":
                String linkId = "";
                if (payMode == 2) {
                    linkId = stringRedisTemplate.opsForValue().get("linkIdType:orgId_" + orgId);
                    if (StringUtils.isEmpty(linkId)) {
                        linkId = purchaseProcessDao.getLinkIdByOrgId(orgId);
                        stringRedisTemplate.opsForValue().set("linkIdType:orgId_" + orgId, linkId);
                    }
                } else if (payMode == 3) {
                    linkId = stringRedisTemplate.opsForValue().get("linkIdType:orgId_linker");
                    if (StringUtils.isEmpty(linkId)) {
                        linkId = purchaseProcessDao.getLinkIdByLinkOrg("linker");
                        stringRedisTemplate.opsForValue().set("linkIdType:orgId_linker", linkId);
                    }
                }
                if (StringUtils.isEmpty(linkId)) {
                    throw GlobalException.build("联汇暂未开户");
                }
                return linkId;
            case "B":
                String orgUid = stringRedisTemplate.opsForValue().get("orgUid:" + orgId);
                if (StringUtils.isEmpty(orgUid)) {
                    orgUid = purchaseProcessDao.getAccountUidByOrgId(orgId);
                    stringRedisTemplate.opsForValue().set("orgUid:" + orgId, orgUid);
                }
                if (StringUtils.isEmpty(orgUid)) {
                    throw GlobalException.build("机构暂未开户");
                }
                return orgUid;
            case "C":
                // 平台营销资金账户
                return "#yunBizUserId_B2C#";
            default:
                throw GlobalException.build("机构账户配置错误！");
        }
    }

    /**
     * 根据费用类型，获得账户类型ABC
     *
     * @param type
     * @param orgId
     * @return
     */
    @Override
    public String getAccountTypeByFeeTypeAndOrgId(String type, String orgId) {
        String accountType = purchaseProcessDao.getAccountTypeByFeeTypeAndOrgId(type, orgId);
        if (StringUtils.isEmpty(accountType)) {
            purchaseProcessDao.insertAcsOrgDefaultConfig(orgId);
            accountType = purchaseProcessDao.getAccountTypeByFeeTypeAndOrgId(type, orgId);
        }
        return accountType;
    }

    /**
     * 生成account数据
     *
     * @param name
     * @param amount
     * @param orgId
     * @return
     * @throws GlobalException
     */
    @Override
    public AccountInfo getAccountMap(String name, Integer amount, String orgId, Integer payMode) throws GlobalException {
        AccountInfo accountInfo = new AccountInfo();
        accountInfo.setName(name);
        accountInfo.setCustomerId(this.getCustomerIdByFeeTypeAndOrdId(name, orgId, payMode));
//        if (accountInfo.getCustomerId().length() == 5) {
//            String uid = purchaseProcessDao.getAccountUidByOrgId(accountInfo.getCustomerId());
//            accountInfo.setCustomerId(uid);
//        }
//        accountInfo.setAccount(purchaseProcessDao.getCustomerAccountNumberByCustomerId(accountInfo.getCustomerId()));
        accountInfo.setAmount(amount);
        accountInfo.setType(this.getAccountTypeByFeeTypeAndOrgId(name, orgId));
        return accountInfo;
    }

    public List copyList(List a) {
        List b = new ArrayList();
        if (a != null && a.size() > 0) {
            for (int i = 0; i < a.size(); i++) {
                b.add(a.get(i));
            }
        }
        return b;
    }

    //增加销量
    public void addSaleNum(Map<String, Object> param) {
        mallDao.editGoodSalesNum(param);
        if (!StringUtils.isEmpty(param.get("skuId"))) {
            mallDao.editGoodSkuSalesNum(param);
        }
        if (!StringUtils.isEmpty(param.get("mallsGoodsId"))) {
            //供货商品加销量
            Long mallsGoodsId = Long.valueOf(param.get("mallsGoodsId").toString());
            Long goodsId = Long.valueOf(param.get("goodsId").toString());
            List<Map<String, Object>> mallsGoodsList = mallDao.getMallsGoodsList(mallsGoodsId, goodsId);
            for (Map<String, Object> da : mallsGoodsList) {
                da.put("buyCount", param.get("buyCount"));
                mallDao.editGoodSalesNum(da);
                if (!StringUtils.isEmpty(param.get("mallsSkuId"))) {
                    da.put("mallsSkuId", param.get("mallsSkuId"));
                    mallDao.editMallGoodSkuSalesNum(param);
                }
            }
        }
    }
}
